blob: 6cce7d21e2d9ca9f6c101abbfa46a050a15cf2ce [file] [log] [blame]
/*
* The Apache Software License, Version 1.1
*
*
* Copyright (c) 1999-2003 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution,
* if any, must include the following acknowledgment:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowledgment may appear in the software itself,
* if and wherever such third-party acknowledgments normally appear.
*
* 4. The names "Xalan" and "Apache Software Foundation" must
* not be used to endorse or promote products derived from this
* software without prior written permission. For written
* permission, please contact apache@apache.org.
*
* 5. Products derived from this software may not be called "Apache",
* nor may "Apache" appear in their name, without prior written
* permission of the Apache Software Foundation.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation and was
* originally based on software copyright (c) 1999, Lotus
* Development Corporation., http://www.lotus.com. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*/
package org.apache.xalan.templates;
import java.util.Hashtable;
import java.util.Vector;
import java.util.Enumeration;
import java.io.Serializable;
//import org.w3c.dom.Node;
import org.apache.xml.dtm.DTM;
import org.apache.xml.dtm.ref.ExpandedNameTable;
import javax.xml.transform.TransformerException;
import org.apache.xml.utils.QName;
import org.apache.xml.utils.PrefixResolver;
import org.apache.xpath.XPath;
import org.apache.xpath.compiler.PsuedoNames;
import org.apache.xpath.patterns.NodeTest;
import org.apache.xpath.Expression;
import org.apache.xalan.res.XSLTErrorResources;
import org.apache.xpath.XPathContext;
import org.apache.xpath.patterns.StepPattern;
import org.apache.xpath.patterns.UnionPattern;
/**
* <meta name="usage" content="advanced"/>
* Encapsulates a template list, and helps locate individual templates.
*/
public class TemplateList implements java.io.Serializable
{
/**
* Construct a TemplateList object. Needs to be public so it can
* be invoked from the CompilingStylesheetHandler.
*/
public TemplateList()
{
super();
}
/**
* Add a template to the table of named templates and/or the table of templates
* with match patterns. This routine should
* be called in decreasing order of precedence but it checks nonetheless.
*
* @param template
*/
public void setTemplate(ElemTemplate template)
{
if (null != template.getName())
{
ElemTemplate existingTemplate = (ElemTemplate) m_namedTemplates.get(template.getName());
if (null == existingTemplate)
{
m_namedTemplates.put(template.getName(), template);
}
else
{
int existingPrecedence =
existingTemplate.getStylesheetComposed().getImportCountComposed();
int newPrecedence = template.getStylesheetComposed().getImportCountComposed();
if (newPrecedence > existingPrecedence)
{
// This should never happen
m_namedTemplates.put(template.getName(), template);
}
else if (newPrecedence == existingPrecedence)
template.error(XSLTErrorResources.ER_DUPLICATE_NAMED_TEMPLATE,
new Object[]{ template.getName() });
}
}
XPath matchXPath = template.getMatch();
if (null != matchXPath)
{
Expression matchExpr = matchXPath.getExpression();
if (matchExpr instanceof StepPattern)
{
insertPatternInTable((StepPattern) matchExpr, template);
}
else if (matchExpr instanceof UnionPattern)
{
UnionPattern upat = (UnionPattern) matchExpr;
StepPattern[] pats = upat.getPatterns();
int n = pats.length;
for (int i = 0; i < n; i++)
{
insertPatternInTable(pats[i], template);
}
}
else
{
// TODO: assert error
}
}
}
/** Flag to indicate whether in DEBUG mode */
static boolean DEBUG = false;
/**
* Dump all patterns and elements that match those patterns
*
*/
void dumpAssociationTables()
{
Enumeration associations = m_patternTable.elements();
while (associations.hasMoreElements())
{
TemplateSubPatternAssociation head =
(TemplateSubPatternAssociation) associations.nextElement();
while (null != head)
{
System.out.print("(" + head.getTargetString() + ", "
+ head.getPattern() + ")");
head = head.getNext();
}
System.out.println("\n.....");
}
TemplateSubPatternAssociation head = m_wildCardPatterns;
System.out.print("wild card list: ");
while (null != head)
{
System.out.print("(" + head.getTargetString() + ", "
+ head.getPattern() + ")");
head = head.getNext();
}
System.out.println("\n.....");
}
/**
* After all templates have been added, this function
* should be called.
*/
public void compose(StylesheetRoot sroot)
{
if (DEBUG)
{
System.out.println("Before wildcard insert...");
dumpAssociationTables();
}
if (null != m_wildCardPatterns)
{
Enumeration associations = m_patternTable.elements();
while (associations.hasMoreElements())
{
TemplateSubPatternAssociation head =
(TemplateSubPatternAssociation) associations.nextElement();
TemplateSubPatternAssociation wild = m_wildCardPatterns;
while (null != wild)
{
try
{
head = insertAssociationIntoList(
head, (TemplateSubPatternAssociation) wild.clone(), true);
}
catch (CloneNotSupportedException cnse){}
wild = wild.getNext();
}
}
}
if (DEBUG)
{
System.out.println("After wildcard insert...");
dumpAssociationTables();
}
}
/**
* Insert the given TemplateSubPatternAssociation into the the linked
* list. Sort by import precedence, then priority, then by document order.
*
* @param head The first TemplateSubPatternAssociation in the linked list.
* @param item The item that we want to insert into the proper place.
* @param isWildCardInsert <code>true</code> if we are inserting a wild card
* template onto this list.
* @return the new head of the list.
*/
private TemplateSubPatternAssociation
insertAssociationIntoList(TemplateSubPatternAssociation head,
TemplateSubPatternAssociation item,
boolean isWildCardInsert)
{
// Sort first by import level (higher level is at front),
// then by priority (highest priority is at front),
// then by document order (later in document is at front).
double priority = getPriorityOrScore(item);
double workPriority;
int importLevel = item.getImportLevel();
int docOrder = item.getDocOrderPos();
TemplateSubPatternAssociation insertPoint = head;
TemplateSubPatternAssociation next;
boolean insertBefore; // true means insert before insertPoint; otherwise after
// This can only be true if insertPoint is pointing to
// the first or last template.
// Spin down so that insertPoint points to:
// (a) the template immediately _before_ the first template on the chain with
// a precedence that is either (i) less than ours or (ii) the same as ours but
// the template document position is less than ours
// -or-
// (b) the last template on the chain if no such template described in (a) exists.
// If we are pointing to the first template or the last template (that is, case b),
// we need to determine whether to insert before or after the template. Otherwise,
// we always insert after the insertPoint.
while (true)
{
next = insertPoint.getNext();
if (null == next)
break;
else
{
workPriority = getPriorityOrScore(next);
if (importLevel > next.getImportLevel())
break;
else if (importLevel < next.getImportLevel())
insertPoint = next;
else if (priority > workPriority) // import precedence is equal
break;
else if (priority < workPriority)
insertPoint = next;
else if (docOrder >= next.getDocOrderPos()) // priorities, import are equal
break;
else
insertPoint = next;
}
}
if ( (null == next) || (insertPoint == head) ) // insert point is first or last
{
workPriority = getPriorityOrScore(insertPoint);
if (importLevel > insertPoint.getImportLevel())
insertBefore = true;
else if (importLevel < insertPoint.getImportLevel())
insertBefore = false;
else if (priority > workPriority)
insertBefore = true;
else if (priority < workPriority)
insertBefore = false;
else if (docOrder >= insertPoint.getDocOrderPos())
insertBefore = true;
else
insertBefore = false;
}
else
insertBefore = false;
// System.out.println("appending: "+target+" to "+matchPat.getPattern());
if (isWildCardInsert)
{
if (insertBefore)
{
item.setNext(insertPoint);
String key = insertPoint.getTargetString();
item.setTargetString(key);
putHead(key, item);
return item;
}
else
{
item.setNext(next);
insertPoint.setNext(item);
return head;
}
}
else
{
if (insertBefore)
{
item.setNext(insertPoint);
if (insertPoint.isWild() || item.isWild())
m_wildCardPatterns = item;
else
putHead(item.getTargetString(), item);
return item;
}
else
{
item.setNext(next);
insertPoint.setNext(item);
return head;
}
}
}
/**
* Add a template to the template list.
*
* @param pattern
* @param template
*/
private void insertPatternInTable(StepPattern pattern, ElemTemplate template)
{
String target = pattern.getTargetString();
if (null != target)
{
String pstring = template.getMatch().getPatternString();
TemplateSubPatternAssociation association =
new TemplateSubPatternAssociation(template, pattern, pstring);
// See if there's already one there
boolean isWildCard = association.isWild();
TemplateSubPatternAssociation head = isWildCard
? m_wildCardPatterns
: getHead(target);
if (null == head)
{
if (isWildCard)
m_wildCardPatterns = association;
else
putHead(target, association);
}
else
{
insertAssociationIntoList(head, association, false);
}
}
}
/**
* Given a match pattern and template association, return the
* score of that match. This score or priority can always be
* statically calculated.
*
* @param matchPat The match pattern to template association.
*
* @return {@link org.apache.xpath.patterns.NodeTest#SCORE_NODETEST},
* {@link org.apache.xpath.patterns.NodeTest#SCORE_NONE},
* {@link org.apache.xpath.patterns.NodeTest#SCORE_NSWILD},
* {@link org.apache.xpath.patterns.NodeTest#SCORE_QNAME}, or
* {@link org.apache.xpath.patterns.NodeTest#SCORE_OTHER}, or
* the value defined by the priority attribute of the template.
*
*/
private double getPriorityOrScore(TemplateSubPatternAssociation matchPat)
{
double priority = matchPat.getTemplate().getPriority();
if (priority == XPath.MATCH_SCORE_NONE)
{
Expression ex = matchPat.getStepPattern();
if (ex instanceof NodeTest)
{
return ((NodeTest) ex).getDefaultScore();
}
}
return priority;
}
/**
* Locate a named template.
*
* @param qname Qualified name of the template.
*
* @return Template argument with the requested name, or null if not found.
*/
public ElemTemplate getTemplate(QName qname)
{
return (ElemTemplate) m_namedTemplates.get(qname);
}
/**
* Get the head of the most likely list of associations to check, based on
* the name and type of the targetNode argument.
*
* @param xctxt The XPath runtime context.
* @param targetNode The target node that will be checked for a match.
* @param dtm The dtm owner for the target node.
*
* @return The head of a linked list that contains all possible match pattern to
* template associations.
*/
public TemplateSubPatternAssociation getHead(XPathContext xctxt,
int targetNode, DTM dtm)
{
short targetNodeType = dtm.getNodeType(targetNode);
TemplateSubPatternAssociation head;
switch (targetNodeType)
{
case DTM.ELEMENT_NODE :
case DTM.ATTRIBUTE_NODE :
head = (TemplateSubPatternAssociation) m_patternTable.get(
dtm.getLocalName(targetNode));
break;
case DTM.TEXT_NODE :
case DTM.CDATA_SECTION_NODE :
head = m_textPatterns;
break;
case DTM.ENTITY_REFERENCE_NODE :
case DTM.ENTITY_NODE :
head = (TemplateSubPatternAssociation) m_patternTable.get(
dtm.getNodeName(targetNode)); // %REVIEW% I think this is right
break;
case DTM.PROCESSING_INSTRUCTION_NODE :
head = (TemplateSubPatternAssociation) m_patternTable.get(
dtm.getLocalName(targetNode));
break;
case DTM.COMMENT_NODE :
head = m_commentPatterns;
break;
case DTM.DOCUMENT_NODE :
case DTM.DOCUMENT_FRAGMENT_NODE :
head = m_docPatterns;
break;
case DTM.NOTATION_NODE :
default :
head = (TemplateSubPatternAssociation) m_patternTable.get(
dtm.getNodeName(targetNode)); // %REVIEW% I think this is right
}
return (null == head) ? m_wildCardPatterns : head;
}
/**
* Given a target element, find the template that best
* matches in the given XSL document, according
* to the rules specified in the xsl draft. This variation of getTemplate
* assumes the current node and current expression node have already been
* pushed.
*
* @param xctxt
* @param targetNode
* @param mode A string indicating the display mode.
* @param maxImportLevel The maximum importCountComposed that we should consider or -1
* if we should consider all import levels. This is used by apply-imports to
* access templates that have been overridden.
* @param quietConflictWarnings
* @return Rule that best matches targetElem.
* @throws XSLProcessorException thrown if the active ProblemListener and XPathContext decide
* the error condition is severe enough to halt processing.
*
* @throws TransformerException
*/
public ElemTemplate getTemplateFast(XPathContext xctxt,
int targetNode,
int expTypeID,
QName mode,
int maxImportLevel,
boolean quietConflictWarnings,
DTM dtm)
throws TransformerException
{
TemplateSubPatternAssociation head;
switch (dtm.getNodeType(targetNode))
{
case DTM.ELEMENT_NODE :
case DTM.ATTRIBUTE_NODE :
head = (TemplateSubPatternAssociation) m_patternTable.get(
dtm.getLocalNameFromExpandedNameID(expTypeID));
break;
case DTM.TEXT_NODE :
case DTM.CDATA_SECTION_NODE :
head = m_textPatterns;
break;
case DTM.ENTITY_REFERENCE_NODE :
case DTM.ENTITY_NODE :
head = (TemplateSubPatternAssociation) m_patternTable.get(
dtm.getNodeName(targetNode)); // %REVIEW% I think this is right
break;
case DTM.PROCESSING_INSTRUCTION_NODE :
head = (TemplateSubPatternAssociation) m_patternTable.get(
dtm.getLocalName(targetNode));
break;
case DTM.COMMENT_NODE :
head = m_commentPatterns;
break;
case DTM.DOCUMENT_NODE :
case DTM.DOCUMENT_FRAGMENT_NODE :
head = m_docPatterns;
break;
case DTM.NOTATION_NODE :
default :
head = (TemplateSubPatternAssociation) m_patternTable.get(
dtm.getNodeName(targetNode)); // %REVIEW% I think this is right
}
if(null == head)
{
head = m_wildCardPatterns;
if(null == head)
return null;
}
// XSLT functions, such as xsl:key, need to be able to get to
// current ElemTemplateElement via a cast to the prefix resolver.
// Setting this fixes bug idkey03.
xctxt.pushNamespaceContextNull();
try
{
do
{
if ( (maxImportLevel > -1) && (head.getImportLevel() > maxImportLevel) )
{
continue;
}
ElemTemplate template = head.getTemplate();
xctxt.setNamespaceContext(template);
if ((head.m_stepPattern.execute(xctxt, targetNode, dtm, expTypeID) != NodeTest.SCORE_NONE)
&& head.matchMode(mode))
{
if (quietConflictWarnings)
checkConflicts(head, xctxt, targetNode, mode);
return template;
}
}
while (null != (head = head.getNext()));
}
finally
{
xctxt.popNamespaceContext();
}
return null;
} // end findTemplate
/**
* Given a target element, find the template that best
* matches in the given XSL document, according
* to the rules specified in the xsl draft.
*
* @param xctxt
* @param targetNode
* @param mode A string indicating the display mode.
* @param quietConflictWarnings
* @return Rule that best matches targetElem.
* @throws XSLProcessorException thrown if the active ProblemListener and XPathContext decide
* the error condition is severe enough to halt processing.
*
* @throws TransformerException
*/
public ElemTemplate getTemplate(XPathContext xctxt,
int targetNode,
QName mode,
boolean quietConflictWarnings,
DTM dtm)
throws TransformerException
{
TemplateSubPatternAssociation head = getHead(xctxt, targetNode, dtm);
if (null != head)
{
// XSLT functions, such as xsl:key, need to be able to get to
// current ElemTemplateElement via a cast to the prefix resolver.
// Setting this fixes bug idkey03.
xctxt.pushNamespaceContextNull();
xctxt.pushCurrentNodeAndExpression(targetNode, targetNode);
try
{
do
{
ElemTemplate template = head.getTemplate();
xctxt.setNamespaceContext(template);
if ((head.m_stepPattern.execute(xctxt, targetNode) != NodeTest.SCORE_NONE)
&& head.matchMode(mode))
{
if (quietConflictWarnings)
checkConflicts(head, xctxt, targetNode, mode);
return template;
}
}
while (null != (head = head.getNext()));
}
finally
{
xctxt.popCurrentNodeAndExpression();
xctxt.popNamespaceContext();
}
}
return null;
} // end findTemplate
/**
* Given a target element, find the template that best
* matches in the given XSL document, according
* to the rules specified in the xsl draft.
*
* @param xctxt
* @param targetNode
* @param mode A string indicating the display mode.
* @param maxImportLevel The maximum importCountComposed that we should consider or -1
* if we should consider all import levels. This is used by apply-imports to
* access templates that have been overridden.
* @param maxEndImportLevel The count of composed imports
* @param quietConflictWarnings
* @return Rule that best matches targetElem.
* @throws XSLProcessorException thrown if the active ProblemListener and XPathContext decide
* the error condition is severe enough to halt processing.
*
* @throws TransformerException
*/
public ElemTemplate getTemplate(XPathContext xctxt,
int targetNode,
QName mode,
int maxImportLevel, int endImportLevel,
boolean quietConflictWarnings,
DTM dtm)
throws TransformerException
{
TemplateSubPatternAssociation head = getHead(xctxt, targetNode, dtm);
if (null != head)
{
// XSLT functions, such as xsl:key, need to be able to get to
// current ElemTemplateElement via a cast to the prefix resolver.
// Setting this fixes bug idkey03.
xctxt.pushNamespaceContextNull();
xctxt.pushCurrentNodeAndExpression(targetNode, targetNode);
try
{
do
{
if ( (maxImportLevel > -1) && (head.getImportLevel() > maxImportLevel))
{
continue;
}
if (head.getImportLevel()<= maxImportLevel - endImportLevel)
return null;
ElemTemplate template = head.getTemplate();
xctxt.setNamespaceContext(template);
if ((head.m_stepPattern.execute(xctxt, targetNode) != NodeTest.SCORE_NONE)
&& head.matchMode(mode))
{
if (quietConflictWarnings)
checkConflicts(head, xctxt, targetNode, mode);
return template;
}
}
while (null != (head = head.getNext()));
}
finally
{
xctxt.popCurrentNodeAndExpression();
xctxt.popNamespaceContext();
}
}
return null;
} // end findTemplate
/**
* Get a TemplateWalker for use by a compiler. See the documentation for
* the TreeWalker inner class for further details.
*/
public TemplateWalker getWalker()
{
return new TemplateWalker();
}
/**
* Check for match conflicts, and warn the stylesheet author.
*
* @param head Template pattern
* @param xctxt Current XPath context
* @param targetNode Node matching the pattern
* @param mode reference, which may be null, to the <a href="http://www.w3.org/TR/xslt#modes">current mode</a>.
*/
private void checkConflicts(TemplateSubPatternAssociation head,
XPathContext xctxt, int targetNode, QName mode)
{
// TODO: Check for conflicts.
}
/**
* Add object to vector if not already there.
*
* @param obj
* @param v
*/
private void addObjectIfNotFound(Object obj, Vector v)
{
int n = v.size();
boolean addIt = true;
for (int i = 0; i < n; i++)
{
if (v.elementAt(i) == obj)
{
addIt = false;
break;
}
}
if (addIt)
{
v.addElement(obj);
}
}
/**
* Keyed on string macro names, and holding values
* that are macro elements in the XSL DOM tree.
* Initialized in initMacroLookupTable, and used in
* findNamedTemplate.
* @serial
*/
private Hashtable m_namedTemplates = new Hashtable(89);
/**
* This table is keyed on the target elements
* of patterns, and contains linked lists of
* the actual patterns that match the target element
* to some degree of specifity.
* @serial
*/
private Hashtable m_patternTable = new Hashtable(89);
/** Wildcard patterns.
* @serial */
private TemplateSubPatternAssociation m_wildCardPatterns = null;
/** Text Patterns.
* @serial */
private TemplateSubPatternAssociation m_textPatterns = null;
/** Root document Patterns.
* @serial */
private TemplateSubPatternAssociation m_docPatterns = null;
/** Comment Patterns.
* @serial */
private TemplateSubPatternAssociation m_commentPatterns = null;
/**
* Get table of named Templates.
* These are keyed on template names, and holding values
* that are template elements.
*
* @return A Hashtable dictionary that contains {@link java.lang.String}s
* as the keys, and {@link org.apache.xalan.templates.ElemTemplate}s as the
* values.
*/
private Hashtable getNamedTemplates()
{
return m_namedTemplates;
}
/**
* Set table of named Templates.
* These are keyed on string macro names, and holding values
* that are template elements in the XSL DOM tree.
*
* @param v Hashtable dictionary that contains {@link java.lang.String}s
* as the keys, and {@link org.apache.xalan.templates.ElemTemplate}s as the
* values.
*/
private void setNamedTemplates(Hashtable v)
{
m_namedTemplates = v;
}
/**
* Get the head of the assocation list that is keyed by target.
*
* @param key The name of a node.
*
* @return The head of a linked list that contains all possible match pattern to
* template associations for the given key.
*/
private TemplateSubPatternAssociation getHead(String key)
{
return (TemplateSubPatternAssociation) m_patternTable.get(key);
}
/**
* Get the head of the assocation list that is keyed by target.
*
* @param key
* @param assoc
*/
private void putHead(String key, TemplateSubPatternAssociation assoc)
{
if (key.equals(PsuedoNames.PSEUDONAME_TEXT))
m_textPatterns = assoc;
else if (key.equals(PsuedoNames.PSEUDONAME_ROOT))
m_docPatterns = assoc;
else if (key.equals(PsuedoNames.PSEUDONAME_COMMENT))
m_commentPatterns = assoc;
m_patternTable.put(key, assoc);
}
/**
* An inner class used by a compiler to iterate over all of the ElemTemplates
* stored in this TemplateList. The compiler can replace returned templates
* with their compiled equivalent.
*/
public class TemplateWalker
{
private Enumeration hashIterator;
private boolean inPatterns;
private TemplateSubPatternAssociation curPattern;
private Hashtable m_compilerCache = new Hashtable();
private TemplateWalker()
{
hashIterator = m_patternTable.elements();
inPatterns = true;
curPattern = null;
}
public ElemTemplate next()
{
ElemTemplate retValue = null;
ElemTemplate ct;
while (true)
{
if (inPatterns)
{
if (null != curPattern)
curPattern = curPattern.getNext();
if (null != curPattern)
retValue = curPattern.getTemplate();
else
{
if (hashIterator.hasMoreElements())
{
curPattern = (TemplateSubPatternAssociation) hashIterator.nextElement();
retValue = curPattern.getTemplate();
}
else
{
inPatterns = false;
hashIterator = m_namedTemplates.elements();
}
}
}
if (!inPatterns)
{
if (hashIterator.hasMoreElements())
retValue = (ElemTemplate) hashIterator.nextElement();
else
return null;
}
ct = (ElemTemplate) m_compilerCache.get(new Integer(retValue.getUid()));
if (null == ct)
{
m_compilerCache.put(new Integer(retValue.getUid()), retValue);
return retValue;
}
}
}
}
}