KickJava   Java API By Example, From Geeks To Geeks.

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


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: TemplateList.java,v 1.38 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.Hashtable JavaDoc;
23 import java.util.Vector JavaDoc;
24
25 import javax.xml.transform.TransformerException JavaDoc;
26
27 import org.apache.xalan.res.XSLTErrorResources;
28 import org.apache.xml.dtm.DTM;
29 import org.apache.xml.utils.QName;
30 import org.apache.xpath.Expression;
31 import org.apache.xpath.XPath;
32 import org.apache.xpath.XPathContext;
33 import org.apache.xpath.compiler.PsuedoNames;
34 import org.apache.xpath.patterns.NodeTest;
35 import org.apache.xpath.patterns.StepPattern;
36 import org.apache.xpath.patterns.UnionPattern;
37
38 /**
39  * Encapsulates a template list, and helps locate individual templates.
40  * @xsl.usage advanced
41  */

42 public class TemplateList implements java.io.Serializable JavaDoc
43 {
44
45   /**
46    * Construct a TemplateList object. Needs to be public so it can
47    * be invoked from the CompilingStylesheetHandler.
48    */

49   public TemplateList()
50   {
51     super();
52   }
53
54   /**
55    * Add a template to the table of named templates and/or the table of templates
56    * with match patterns. This routine should
57    * be called in decreasing order of precedence but it checks nonetheless.
58    *
59    * @param template
60    */

61   public void setTemplate(ElemTemplate template)
62   {
63     XPath matchXPath = template.getMatch();
64     
65     if (null == template.getName() && null == matchXPath)
66     {
67       template.error(XSLTErrorResources.ER_NEED_NAME_OR_MATCH_ATTRIB,
68           new Object JavaDoc[]{ "xsl:template" });
69     }
70     
71     if (null != template.getName())
72     {
73       ElemTemplate existingTemplate = (ElemTemplate) m_namedTemplates.get(template.getName());
74       if (null == existingTemplate)
75       {
76         m_namedTemplates.put(template.getName(), template);
77       }
78       else
79       {
80         int existingPrecedence =
81                         existingTemplate.getStylesheetComposed().getImportCountComposed();
82         int newPrecedence = template.getStylesheetComposed().getImportCountComposed();
83         if (newPrecedence > existingPrecedence)
84         {
85           // This should never happen
86
m_namedTemplates.put(template.getName(), template);
87         }
88         else if (newPrecedence == existingPrecedence)
89           template.error(XSLTErrorResources.ER_DUPLICATE_NAMED_TEMPLATE,
90                        new Object JavaDoc[]{ template.getName() });
91       }
92     }
93
94     
95
96     if (null != matchXPath)
97     {
98       Expression matchExpr = matchXPath.getExpression();
99
100       if (matchExpr instanceof StepPattern)
101       {
102         insertPatternInTable((StepPattern) matchExpr, template);
103       }
104       else if (matchExpr instanceof UnionPattern)
105       {
106         UnionPattern upat = (UnionPattern) matchExpr;
107         StepPattern[] pats = upat.getPatterns();
108         int n = pats.length;
109
110         for (int i = 0; i < n; i++)
111         {
112           insertPatternInTable(pats[i], template);
113         }
114       }
115       else
116       {
117
118         // TODO: assert error
119
}
120     }
121   }
122
123   /** Flag to indicate whether in DEBUG mode */
124   static boolean DEBUG = false;
125
126   /**
127    * Dump all patterns and elements that match those patterns
128    *
129    */

130   void dumpAssociationTables()
131   {
132
133     Enumeration JavaDoc associations = m_patternTable.elements();
134
135     while (associations.hasMoreElements())
136     {
137       TemplateSubPatternAssociation head =
138         (TemplateSubPatternAssociation) associations.nextElement();
139
140       while (null != head)
141       {
142         System.out.print("(" + head.getTargetString() + ", "
143                          + head.getPattern() + ")");
144
145         head = head.getNext();
146       }
147
148       System.out.println("\n.....");
149     }
150
151     TemplateSubPatternAssociation head = m_wildCardPatterns;
152
153     System.out.print("wild card list: ");
154
155     while (null != head)
156     {
157       System.out.print("(" + head.getTargetString() + ", "
158                        + head.getPattern() + ")");
159
160       head = head.getNext();
161     }
162
163     System.out.println("\n.....");
164   }
165
166   /**
167    * After all templates have been added, this function
168    * should be called.
169    */

170   public void compose(StylesheetRoot sroot)
171   {
172
173     if (DEBUG)
174     {
175       System.out.println("Before wildcard insert...");
176       dumpAssociationTables();
177     }
178
179     if (null != m_wildCardPatterns)
180     {
181       Enumeration JavaDoc associations = m_patternTable.elements();
182
183       while (associations.hasMoreElements())
184       {
185         TemplateSubPatternAssociation head =
186           (TemplateSubPatternAssociation) associations.nextElement();
187         TemplateSubPatternAssociation wild = m_wildCardPatterns;
188
189         while (null != wild)
190         {
191           try
192           {
193             head = insertAssociationIntoList(
194               head, (TemplateSubPatternAssociation) wild.clone(), true);
195           }
196           catch (CloneNotSupportedException JavaDoc cnse){}
197
198           wild = wild.getNext();
199         }
200       }
201     }
202
203     if (DEBUG)
204     {
205       System.out.println("After wildcard insert...");
206       dumpAssociationTables();
207     }
208   }
209
210   /**
211    * Insert the given TemplateSubPatternAssociation into the the linked
212    * list. Sort by import precedence, then priority, then by document order.
213    *
214    * @param head The first TemplateSubPatternAssociation in the linked list.
215    * @param item The item that we want to insert into the proper place.
216    * @param isWildCardInsert <code>true</code> if we are inserting a wild card
217    * template onto this list.
218    * @return the new head of the list.
219    */

220   private TemplateSubPatternAssociation
221               insertAssociationIntoList(TemplateSubPatternAssociation head,
222                                          TemplateSubPatternAssociation item,
223                                          boolean isWildCardInsert)
224   {
225
226     // Sort first by import level (higher level is at front),
227
// then by priority (highest priority is at front),
228
// then by document order (later in document is at front).
229

230     double priority = getPriorityOrScore(item);
231     double workPriority;
232     int importLevel = item.getImportLevel();
233     int docOrder = item.getDocOrderPos();
234     TemplateSubPatternAssociation insertPoint = head;
235     TemplateSubPatternAssociation next;
236     boolean insertBefore; // true means insert before insertPoint; otherwise after
237
// This can only be true if insertPoint is pointing to
238
// the first or last template.
239

240     // Spin down so that insertPoint points to:
241
// (a) the template immediately _before_ the first template on the chain with
242
// a precedence that is either (i) less than ours or (ii) the same as ours but
243
// the template document position is less than ours
244
// -or-
245
// (b) the last template on the chain if no such template described in (a) exists.
246
// If we are pointing to the first template or the last template (that is, case b),
247
// we need to determine whether to insert before or after the template. Otherwise,
248
// we always insert after the insertPoint.
249

250     while (true)
251     {
252       next = insertPoint.getNext();
253       if (null == next)
254         break;
255       else
256       {
257         workPriority = getPriorityOrScore(next);
258         if (importLevel > next.getImportLevel())
259           break;
260         else if (importLevel < next.getImportLevel())
261           insertPoint = next;
262         else if (priority > workPriority) // import precedence is equal
263
break;
264         else if (priority < workPriority)
265           insertPoint = next;
266         else if (docOrder >= next.getDocOrderPos()) // priorities, import are equal
267
break;
268         else
269           insertPoint = next;
270       }
271     }
272
273     if ( (null == next) || (insertPoint == head) ) // insert point is first or last
274
{
275       workPriority = getPriorityOrScore(insertPoint);
276       if (importLevel > insertPoint.getImportLevel())
277         insertBefore = true;
278       else if (importLevel < insertPoint.getImportLevel())
279         insertBefore = false;
280       else if (priority > workPriority)
281         insertBefore = true;
282       else if (priority < workPriority)
283         insertBefore = false;
284       else if (docOrder >= insertPoint.getDocOrderPos())
285         insertBefore = true;
286       else
287         insertBefore = false;
288     }
289     else
290       insertBefore = false;
291
292     // System.out.println("appending: "+target+" to "+matchPat.getPattern());
293

294     if (isWildCardInsert)
295     {
296       if (insertBefore)
297       {
298         item.setNext(insertPoint);
299
300         String JavaDoc key = insertPoint.getTargetString();
301
302         item.setTargetString(key);
303         putHead(key, item);
304         return item;
305       }
306       else
307       {
308         item.setNext(next);
309         insertPoint.setNext(item);
310         return head;
311       }
312     }
313     else
314     {
315       if (insertBefore)
316       {
317         item.setNext(insertPoint);
318
319         if (insertPoint.isWild() || item.isWild())
320           m_wildCardPatterns = item;
321         else
322           putHead(item.getTargetString(), item);
323         return item;
324       }
325       else
326       {
327         item.setNext(next);
328         insertPoint.setNext(item);
329         return head;
330       }
331     }
332   }
333
334   /**
335    * Add a template to the template list.
336    *
337    * @param pattern
338    * @param template
339    */

340   private void insertPatternInTable(StepPattern pattern, ElemTemplate template)
341   {
342
343     String JavaDoc target = pattern.getTargetString();
344
345     if (null != target)
346     {
347       String JavaDoc pstring = template.getMatch().getPatternString();
348       TemplateSubPatternAssociation association =
349         new TemplateSubPatternAssociation(template, pattern, pstring);
350
351       // See if there's already one there
352
boolean isWildCard = association.isWild();
353       TemplateSubPatternAssociation head = isWildCard
354                                            ? m_wildCardPatterns
355                                            : getHead(target);
356
357       if (null == head)
358       {
359         if (isWildCard)
360           m_wildCardPatterns = association;
361         else
362           putHead(target, association);
363       }
364       else
365       {
366         insertAssociationIntoList(head, association, false);
367       }
368     }
369   }
370
371   /**
372    * Given a match pattern and template association, return the
373    * score of that match. This score or priority can always be
374    * statically calculated.
375    *
376    * @param matchPat The match pattern to template association.
377    *
378    * @return {@link org.apache.xpath.patterns.NodeTest#SCORE_NODETEST},
379    * {@link org.apache.xpath.patterns.NodeTest#SCORE_NONE},
380    * {@link org.apache.xpath.patterns.NodeTest#SCORE_NSWILD},
381    * {@link org.apache.xpath.patterns.NodeTest#SCORE_QNAME}, or
382    * {@link org.apache.xpath.patterns.NodeTest#SCORE_OTHER}, or
383    * the value defined by the priority attribute of the template.
384    *
385    */

386   private double getPriorityOrScore(TemplateSubPatternAssociation matchPat)
387   {
388
389     double priority = matchPat.getTemplate().getPriority();
390
391     if (priority == XPath.MATCH_SCORE_NONE)
392     {
393       Expression ex = matchPat.getStepPattern();
394
395       if (ex instanceof NodeTest)
396       {
397         return ((NodeTest) ex).getDefaultScore();
398       }
399     }
400
401     return priority;
402   }
403
404   /**
405    * Locate a named template.
406    *
407    * @param qname Qualified name of the template.
408    *
409    * @return Template argument with the requested name, or null if not found.
410    */

411   public ElemTemplate getTemplate(QName qname)
412   {
413     return (ElemTemplate) m_namedTemplates.get(qname);
414   }
415
416   /**
417    * Get the head of the most likely list of associations to check, based on
418    * the name and type of the targetNode argument.
419    *
420    * @param xctxt The XPath runtime context.
421    * @param targetNode The target node that will be checked for a match.
422    * @param dtm The dtm owner for the target node.
423    *
424    * @return The head of a linked list that contains all possible match pattern to
425    * template associations.
426    */

427   public TemplateSubPatternAssociation getHead(XPathContext xctxt,
428                                                int targetNode, DTM dtm)
429   {
430     short targetNodeType = dtm.getNodeType(targetNode);
431     TemplateSubPatternAssociation head;
432
433     switch (targetNodeType)
434     {
435     case DTM.ELEMENT_NODE :
436     case DTM.ATTRIBUTE_NODE :
437       head = (TemplateSubPatternAssociation) m_patternTable.get(
438         dtm.getLocalName(targetNode));
439       break;
440     case DTM.TEXT_NODE :
441     case DTM.CDATA_SECTION_NODE :
442       head = m_textPatterns;
443       break;
444     case DTM.ENTITY_REFERENCE_NODE :
445     case DTM.ENTITY_NODE :
446       head = (TemplateSubPatternAssociation) m_patternTable.get(
447         dtm.getNodeName(targetNode)); // %REVIEW% I think this is right
448
break;
449     case DTM.PROCESSING_INSTRUCTION_NODE :
450       head = (TemplateSubPatternAssociation) m_patternTable.get(
451         dtm.getLocalName(targetNode));
452       break;
453     case DTM.COMMENT_NODE :
454       head = m_commentPatterns;
455       break;
456     case DTM.DOCUMENT_NODE :
457     case DTM.DOCUMENT_FRAGMENT_NODE :
458       head = m_docPatterns;
459       break;
460     case DTM.NOTATION_NODE :
461     default :
462       head = (TemplateSubPatternAssociation) m_patternTable.get(
463         dtm.getNodeName(targetNode)); // %REVIEW% I think this is right
464
}
465
466     return (null == head) ? m_wildCardPatterns : head;
467   }
468   
469   /**
470    * Given a target element, find the template that best
471    * matches in the given XSL document, according
472    * to the rules specified in the xsl draft. This variation of getTemplate
473    * assumes the current node and current expression node have already been
474    * pushed.
475    *
476    * @param xctxt
477    * @param targetNode
478    * @param mode A string indicating the display mode.
479    * @param maxImportLevel The maximum importCountComposed that we should consider or -1
480    * if we should consider all import levels. This is used by apply-imports to
481    * access templates that have been overridden.
482    * @param quietConflictWarnings
483    * @return Rule that best matches targetElem.
484    * @throws XSLProcessorException thrown if the active ProblemListener and XPathContext decide
485    * the error condition is severe enough to halt processing.
486    *
487    * @throws TransformerException
488    */

489   public ElemTemplate getTemplateFast(XPathContext xctxt,
490                                 int targetNode,
491                                 int expTypeID,
492                                 QName mode,
493                                 int maxImportLevel,
494                                 boolean quietConflictWarnings,
495                                 DTM dtm)
496             throws TransformerException JavaDoc
497   {
498     
499     TemplateSubPatternAssociation head;
500
501     switch (dtm.getNodeType(targetNode))
502     {
503     case DTM.ELEMENT_NODE :
504     case DTM.ATTRIBUTE_NODE :
505       head = (TemplateSubPatternAssociation) m_patternTable.get(
506         dtm.getLocalNameFromExpandedNameID(expTypeID));
507       break;
508     case DTM.TEXT_NODE :
509     case DTM.CDATA_SECTION_NODE :
510       head = m_textPatterns;
511       break;
512     case DTM.ENTITY_REFERENCE_NODE :
513     case DTM.ENTITY_NODE :
514       head = (TemplateSubPatternAssociation) m_patternTable.get(
515         dtm.getNodeName(targetNode)); // %REVIEW% I think this is right
516
break;
517     case DTM.PROCESSING_INSTRUCTION_NODE :
518       head = (TemplateSubPatternAssociation) m_patternTable.get(
519         dtm.getLocalName(targetNode));
520       break;
521     case DTM.COMMENT_NODE :
522       head = m_commentPatterns;
523       break;
524     case DTM.DOCUMENT_NODE :
525     case DTM.DOCUMENT_FRAGMENT_NODE :
526       head = m_docPatterns;
527       break;
528     case DTM.NOTATION_NODE :
529     default :
530       head = (TemplateSubPatternAssociation) m_patternTable.get(
531         dtm.getNodeName(targetNode)); // %REVIEW% I think this is right
532
}
533
534     if(null == head)
535     {
536       head = m_wildCardPatterns;
537       if(null == head)
538         return null;
539     }
540
541     // XSLT functions, such as xsl:key, need to be able to get to
542
// current ElemTemplateElement via a cast to the prefix resolver.
543
// Setting this fixes bug idkey03.
544
xctxt.pushNamespaceContextNull();
545     try
546     {
547       do
548       {
549         if ( (maxImportLevel > -1) && (head.getImportLevel() > maxImportLevel) )
550         {
551           continue;
552         }
553         ElemTemplate template = head.getTemplate();
554         xctxt.setNamespaceContext(template);
555         
556         if ((head.m_stepPattern.execute(xctxt, targetNode, dtm, expTypeID) != NodeTest.SCORE_NONE)
557                 && head.matchMode(mode))
558         {
559           if (quietConflictWarnings)
560             checkConflicts(head, xctxt, targetNode, mode);
561
562           return template;
563         }
564       }
565       while (null != (head = head.getNext()));
566     }
567     finally
568     {
569       xctxt.popNamespaceContext();
570     }
571
572     return null;
573   } // end findTemplate
574

575   /**
576    * Given a target element, find the template that best
577    * matches in the given XSL document, according
578    * to the rules specified in the xsl draft.
579    *
580    * @param xctxt
581    * @param targetNode
582    * @param mode A string indicating the display mode.
583    * @param quietConflictWarnings
584    * @return Rule that best matches targetElem.
585    * @throws XSLProcessorException thrown if the active ProblemListener and XPathContext decide
586    * the error condition is severe enough to halt processing.
587    *
588    * @throws TransformerException
589    */

590   public ElemTemplate getTemplate(XPathContext xctxt,
591                                 int targetNode,
592                                 QName mode,
593                                 boolean quietConflictWarnings,
594                                 DTM dtm)
595             throws TransformerException JavaDoc
596   {
597
598     TemplateSubPatternAssociation head = getHead(xctxt, targetNode, dtm);
599
600     if (null != head)
601     {
602       // XSLT functions, such as xsl:key, need to be able to get to
603
// current ElemTemplateElement via a cast to the prefix resolver.
604
// Setting this fixes bug idkey03.
605
xctxt.pushNamespaceContextNull();
606       xctxt.pushCurrentNodeAndExpression(targetNode, targetNode);
607       try
608       {
609         do
610         {
611           ElemTemplate template = head.getTemplate();
612           xctxt.setNamespaceContext(template);
613           
614           if ((head.m_stepPattern.execute(xctxt, targetNode) != NodeTest.SCORE_NONE)
615                   && head.matchMode(mode))
616           {
617             if (quietConflictWarnings)
618               checkConflicts(head, xctxt, targetNode, mode);
619
620             return template;
621           }
622         }
623         while (null != (head = head.getNext()));
624       }
625       finally
626       {
627         xctxt.popCurrentNodeAndExpression();
628         xctxt.popNamespaceContext();
629       }
630     }
631
632     return null;
633   } // end findTemplate
634

635   /**
636    * Given a target element, find the template that best
637    * matches in the given XSL document, according
638    * to the rules specified in the xsl draft.
639    *
640    * @param xctxt
641    * @param targetNode
642    * @param mode A string indicating the display mode.
643    * @param maxImportLevel The maximum importCountComposed that we should consider or -1
644    * if we should consider all import levels. This is used by apply-imports to
645    * access templates that have been overridden.
646    * @param maxEndImportLevel The count of composed imports
647    * @param quietConflictWarnings
648    * @return Rule that best matches targetElem.
649    * @throws XSLProcessorException thrown if the active ProblemListener and XPathContext decide
650    * the error condition is severe enough to halt processing.
651    *
652    * @throws TransformerException
653    */

654   public ElemTemplate getTemplate(XPathContext xctxt,
655                                 int targetNode,
656                                 QName mode,
657                                 int maxImportLevel, int endImportLevel,
658                                 boolean quietConflictWarnings,
659                                 DTM dtm)
660             throws TransformerException JavaDoc
661   {
662
663     TemplateSubPatternAssociation head = getHead(xctxt, targetNode, dtm);
664
665     if (null != head)
666     {
667       // XSLT functions, such as xsl:key, need to be able to get to
668
// current ElemTemplateElement via a cast to the prefix resolver.
669
// Setting this fixes bug idkey03.
670
xctxt.pushNamespaceContextNull();
671       xctxt.pushCurrentNodeAndExpression(targetNode, targetNode);
672       try
673       {
674         do
675         {
676           if ( (maxImportLevel > -1) && (head.getImportLevel() > maxImportLevel))
677           {
678             continue;
679           }
680           if (head.getImportLevel()<= maxImportLevel - endImportLevel)
681             return null;
682           ElemTemplate template = head.getTemplate();
683           xctxt.setNamespaceContext(template);
684           
685           if ((head.m_stepPattern.execute(xctxt, targetNode) != NodeTest.SCORE_NONE)
686                   && head.matchMode(mode))
687           {
688             if (quietConflictWarnings)
689               checkConflicts(head, xctxt, targetNode, mode);
690
691             return template;
692           }
693         }
694         while (null != (head = head.getNext()));
695       }
696       finally
697       {
698         xctxt.popCurrentNodeAndExpression();
699         xctxt.popNamespaceContext();
700       }
701     }
702
703     return null;
704   } // end findTemplate
705

706   /**
707    * Get a TemplateWalker for use by a compiler. See the documentation for
708    * the TreeWalker inner class for further details.
709    */

710   public TemplateWalker getWalker()
711   {
712     return new TemplateWalker();
713   }
714
715   /**
716    * Check for match conflicts, and warn the stylesheet author.
717    *
718    * @param head Template pattern
719    * @param xctxt Current XPath context
720    * @param targetNode Node matching the pattern
721    * @param mode reference, which may be null, to the <a HREF="http://www.w3.org/TR/xslt#modes">current mode</a>.
722    */

723   private void checkConflicts(TemplateSubPatternAssociation head,
724                               XPathContext xctxt, int targetNode, QName mode)
725   {
726
727     // TODO: Check for conflicts.
728
}
729
730   /**
731    * Add object to vector if not already there.
732    *
733    * @param obj
734    * @param v
735    */

736   private void addObjectIfNotFound(Object JavaDoc obj, Vector JavaDoc v)
737   {
738
739     int n = v.size();
740     boolean addIt = true;
741
742     for (int i = 0; i < n; i++)
743     {
744       if (v.elementAt(i) == obj)
745       {
746         addIt = false;
747
748         break;
749       }
750     }
751
752     if (addIt)
753     {
754       v.addElement(obj);
755     }
756   }
757
758   /**
759    * Keyed on string macro names, and holding values
760    * that are macro elements in the XSL DOM tree.
761    * Initialized in initMacroLookupTable, and used in
762    * findNamedTemplate.
763    * @serial
764    */

765   private Hashtable JavaDoc m_namedTemplates = new Hashtable JavaDoc(89);
766
767   /**
768    * This table is keyed on the target elements
769    * of patterns, and contains linked lists of
770    * the actual patterns that match the target element
771    * to some degree of specifity.
772    * @serial
773    */

774   private Hashtable JavaDoc m_patternTable = new Hashtable JavaDoc(89);
775
776   /** Wildcard patterns.
777    * @serial */

778   private TemplateSubPatternAssociation m_wildCardPatterns = null;
779
780   /** Text Patterns.
781    * @serial */

782   private TemplateSubPatternAssociation m_textPatterns = null;
783
784   /** Root document Patterns.
785    * @serial */

786   private TemplateSubPatternAssociation m_docPatterns = null;
787
788   /** Comment Patterns.
789    * @serial */

790   private TemplateSubPatternAssociation m_commentPatterns = null;
791
792   /**
793    * Get table of named Templates.
794    * These are keyed on template names, and holding values
795    * that are template elements.
796    *
797    * @return A Hashtable dictionary that contains {@link java.lang.String}s
798    * as the keys, and {@link org.apache.xalan.templates.ElemTemplate}s as the
799    * values.
800    */

801   private Hashtable JavaDoc getNamedTemplates()
802   {
803     return m_namedTemplates;
804   }
805
806   /**
807    * Set table of named Templates.
808    * These are keyed on string macro names, and holding values
809    * that are template elements in the XSL DOM tree.
810    *
811    * @param v Hashtable dictionary that contains {@link java.lang.String}s
812    * as the keys, and {@link org.apache.xalan.templates.ElemTemplate}s as the
813    * values.
814    */

815   private void setNamedTemplates(Hashtable JavaDoc v)
816   {
817     m_namedTemplates = v;
818   }
819
820   /**
821    * Get the head of the assocation list that is keyed by target.
822    *
823    * @param key The name of a node.
824    *
825    * @return The head of a linked list that contains all possible match pattern to
826    * template associations for the given key.
827    */

828   private TemplateSubPatternAssociation getHead(String JavaDoc key)
829   {
830     return (TemplateSubPatternAssociation) m_patternTable.get(key);
831   }
832
833   /**
834    * Get the head of the assocation list that is keyed by target.
835    *
836    * @param key
837    * @param assoc
838    */

839   private void putHead(String JavaDoc key, TemplateSubPatternAssociation assoc)
840   {
841
842     if (key.equals(PsuedoNames.PSEUDONAME_TEXT))
843       m_textPatterns = assoc;
844     else if (key.equals(PsuedoNames.PSEUDONAME_ROOT))
845       m_docPatterns = assoc;
846     else if (key.equals(PsuedoNames.PSEUDONAME_COMMENT))
847       m_commentPatterns = assoc;
848
849     m_patternTable.put(key, assoc);
850   }
851
852   /**
853    * An inner class used by a compiler to iterate over all of the ElemTemplates
854    * stored in this TemplateList. The compiler can replace returned templates
855    * with their compiled equivalent.
856    */

857   public class TemplateWalker
858   {
859     private Enumeration JavaDoc hashIterator;
860     private boolean inPatterns;
861     private TemplateSubPatternAssociation curPattern;
862
863     private Hashtable JavaDoc m_compilerCache = new Hashtable JavaDoc();
864
865     private TemplateWalker()
866     {
867       hashIterator = m_patternTable.elements();
868       inPatterns = true;
869       curPattern = null;
870     }
871
872     public ElemTemplate next()
873     {
874
875       ElemTemplate retValue = null;
876       ElemTemplate ct;
877
878       while (true)
879       {
880         if (inPatterns)
881         {
882           if (null != curPattern)
883             curPattern = curPattern.getNext();
884
885           if (null != curPattern)
886             retValue = curPattern.getTemplate();
887           else
888           {
889             if (hashIterator.hasMoreElements())
890             {
891               curPattern = (TemplateSubPatternAssociation) hashIterator.nextElement();
892               retValue = curPattern.getTemplate();
893             }
894             else
895             {
896               inPatterns = false;
897               hashIterator = m_namedTemplates.elements();
898             }
899           }
900         }
901
902         if (!inPatterns)
903         {
904           if (hashIterator.hasMoreElements())
905             retValue = (ElemTemplate) hashIterator.nextElement();
906           else
907             return null;
908         }
909
910         ct = (ElemTemplate) m_compilerCache.get(new Integer JavaDoc(retValue.getUid()));
911         if (null == ct)
912         {
913           m_compilerCache.put(new Integer JavaDoc(retValue.getUid()), retValue);
914           return retValue;
915         }
916       }
917     }
918   }
919
920 }
921
Popular Tags