}
public void compileApplyImports(ClassGenerator classGen, int min, int max) {
final XSLTC xsltc = classGen.getParser().getXSLTC();
final ConstantPoolGen cpg = classGen.getConstantPool();
final Vector names = xsltc.getNamesIndex();
// Clear some datastructures
_namedTemplates = new Hashtable();
_neededTemplates = new Hashtable();
_templateIHs = new Hashtable();
_templateILs = new Hashtable();
_patternGroups = new Vector[32];
_rootPattern = null;
// IMPORTANT: Save orignal & complete set of templates!!!!
Vector oldTemplates = _templates;
// Gather templates that are within the scope of this import
_templates = new Vector();
final Enumeration templates = oldTemplates.elements();
while (templates.hasMoreElements()) {
final Template template = (Template)templates.nextElement();
final int prec = template.getImportPrecedence();
if ((prec >= min) && (prec < max)) addTemplate(template);
}
// Process all patterns from those templates
processPatterns(_keys);
// Create the applyTemplates() method
final com.sun.org.apache.bcel.internal.generic.Type[] argTypes =
new com.sun.org.apache.bcel.internal.generic.Type[4];
argTypes[0] = Util.getJCRefType(DOM_INTF_SIG);
argTypes[1] = Util.getJCRefType(NODE_ITERATOR_SIG);
argTypes[2] = Util.getJCRefType(TRANSLET_OUTPUT_SIG);
argTypes[3] = com.sun.org.apache.bcel.internal.generic.Type.INT;
final String[] argNames = new String[4];
argNames[0] = DOCUMENT_PNAME;
argNames[1] = ITERATOR_PNAME;
argNames[2] = TRANSLET_OUTPUT_PNAME;
argNames[3] = NODE_PNAME;
final InstructionList mainIL = new InstructionList();
final MethodGenerator methodGen =
new MethodGenerator(ACC_PUBLIC | ACC_FINAL,
com.sun.org.apache.bcel.internal.generic.Type.VOID,
argTypes, argNames, functionName()+'_'+max,
getClassName(), mainIL,
classGen.getConstantPool());
methodGen.addException("com.sun.org.apache.xalan.internal.xsltc.TransletException");
// Create the local variable to hold the current node
final LocalVariableGen current;
current = methodGen.addLocalVariable2("current",
com.sun.org.apache.bcel.internal.generic.Type.INT,
null);
_currentIndex = current.getIndex();
mainIL.append(new ILOAD(methodGen.getLocalIndex(NODE_PNAME)));
current.setStart(mainIL.append(new ISTORE(_currentIndex)));
// Create the "body" instruction list that will eventually hold the
// code for the entire method (other ILs will be appended).
final InstructionList body = new InstructionList();
body.append(NOP);
// Create an instruction list that contains the default next-node
// iteration
final InstructionList ilLoop = new InstructionList();
ilLoop.append(RETURN);
final InstructionHandle ihLoop = ilLoop.getStart();
// Compile default handling of elements (traverse children)
InstructionList ilRecurse =
compileDefaultRecursion(classGen, methodGen, ihLoop);
InstructionHandle ihRecurse = ilRecurse.getStart();
// Compile default handling of text/attribute nodes (output text)
InstructionList ilText =
compileDefaultText(classGen, methodGen, ihLoop);
InstructionHandle ihText = ilText.getStart();
// Distinguish attribute/element/namespace tests for further processing
final int[] types = new int[DTM.NTYPES + names.size()];
for (int i = 0; i < types.length; i++) {
types[i] = i;
}
final boolean[] isAttribute = new boolean[types.length];
final boolean[] isNamespace = new boolean[types.length];
for (int i = 0; i < names.size(); i++) {
final String name = (String)names.elementAt(i);
isAttribute[i+DTM.NTYPES] = isAttributeName(name);
isNamespace[i+DTM.NTYPES] = isNamespaceName(name);
}
// Compile all templates - regardless of pattern type
compileTemplateCalls(classGen, methodGen, ihLoop, min, max);
// Handle template with explicit "*" pattern
final TestSeq elemTest = _testSeq[DTM.ELEMENT_NODE];
InstructionHandle ihElem = ihRecurse;
if (elemTest != null) {
ihElem = elemTest.compile(classGen, methodGen, ihLoop);
}
// Handle template with explicit "@*" pattern
final TestSeq attrTest = _testSeq[DTM.ATTRIBUTE_NODE];
InstructionHandle ihAttr = ihLoop;
if (attrTest != null) {
ihAttr = attrTest.compile(classGen, methodGen, ihAttr);
}
// Do tests for id() and key() patterns first
InstructionList ilKey = null;
if (_idxTestSeq != null) {
ilKey = _idxTestSeq.getInstructionList();
}
// If there is a match on node() we need to replace ihElem
// and ihText if the priority of node() is higher
if (_childNodeTestSeq != null) {
// Compare priorities of node() and "*"
double nodePrio = _childNodeTestSeq.getPriority();
int nodePos = _childNodeTestSeq.getPosition();
double elemPrio = (0 - Double.MAX_VALUE);
int elemPos = Integer.MIN_VALUE;
if (elemTest != null) {
elemPrio = elemTest.getPriority();
elemPos = elemTest.getPosition();
}
if (elemPrio == Double.NaN || elemPrio < nodePrio ||
(elemPrio == nodePrio && elemPos < nodePos))
{
ihElem = _childNodeTestSeq.compile(classGen, methodGen, ihLoop);
}
// Compare priorities of node() and text()
final TestSeq textTest = _testSeq[DTM.TEXT_NODE];
double textPrio = (0 - Double.MAX_VALUE);
int textPos = Integer.MIN_VALUE;
if (textTest != null) {
textPrio = textTest.getPriority();
textPos = textTest.getPosition();
}
if (textPrio == Double.NaN || textPrio < nodePrio ||
(textPrio == nodePrio && textPos < nodePos))
{
ihText = _childNodeTestSeq.compile(classGen, methodGen, ihLoop);
_testSeq[DTM.TEXT_NODE] = _childNodeTestSeq;
}
}
// Handle templates with "ns:*" pattern
InstructionHandle elemNamespaceHandle = ihElem;
InstructionList nsElem = compileNamespaces(classGen, methodGen,
isNamespace, isAttribute,
false, ihElem);
if (nsElem != null) elemNamespaceHandle = nsElem.getStart();
// Handle templates with "ns:@*" pattern
InstructionList nsAttr = compileNamespaces(classGen, methodGen,
isNamespace, isAttribute,
true, ihAttr);
InstructionHandle attrNamespaceHandle = ihAttr;
if (nsAttr != null) attrNamespaceHandle = nsAttr.getStart();
// Handle templates with "ns:elem" or "ns:@attr" pattern
final InstructionHandle[] targets = new InstructionHandle[types.length];
for (int i = DTM.NTYPES; i < targets.length; i++) {
final TestSeq testSeq = _testSeq[i];
// Jump straight to namespace tests ?
if (isNamespace[i]) {
if (isAttribute[i])
targets[i] = attrNamespaceHandle;
else
targets[i] = elemNamespaceHandle;
}
// Test first, then jump to namespace tests
else if (testSeq != null) {
if (isAttribute[i])
targets[i] = testSeq.compile(classGen, methodGen,
attrNamespaceHandle);
else
targets[i] = testSeq.compile(classGen, methodGen,
elemNamespaceHandle);
}
else {
targets[i] = ihLoop;
}
}
// Handle pattern with match on root node - default: traverse children
targets[DTM.ROOT_NODE] = _rootPattern != null
? getTemplateInstructionHandle(_rootPattern.getTemplate())
: ihRecurse;
// Handle pattern with match on root node - default: traverse children
targets[DTM.DOCUMENT_NODE] = _rootPattern != null
? getTemplateInstructionHandle(_rootPattern.getTemplate())
: ihRecurse; // %HZ%: Was ihLoop in XSLTC_DTM branch
// Handle any pattern with match on text nodes - default: loop
targets[DTM.TEXT_NODE] = _testSeq[DTM.TEXT_NODE] != null
? _testSeq[DTM.TEXT_NODE].compile(classGen, methodGen, ihText)
: ihText;
// This DOM-type is not in use - default: process next node
targets[DTM.NAMESPACE_NODE] = ihLoop;
// Match unknown element in DOM - default: check for namespace match
targets[DTM.ELEMENT_NODE] = elemNamespaceHandle;
// Match unknown attribute in DOM - default: check for namespace match
targets[DTM.ATTRIBUTE_NODE] = attrNamespaceHandle;
// Match on processing instruction - default: loop
InstructionHandle ihPI = ihLoop;
if (_childNodeTestSeq != null) ihPI = ihElem;
if (_testSeq[DTM.PROCESSING_INSTRUCTION_NODE] != null) {
targets[DTM.PROCESSING_INSTRUCTION_NODE] =
_testSeq[DTM.PROCESSING_INSTRUCTION_NODE].
compile(classGen, methodGen, ihPI);
}
else {
targets[DTM.PROCESSING_INSTRUCTION_NODE] = ihPI;
}
// Match on comments - default: process next node
InstructionHandle ihComment = ihLoop;
if (_childNodeTestSeq != null) ihComment = ihElem;
targets[DTM.COMMENT_NODE] = _testSeq[DTM.COMMENT_NODE] != null
? _testSeq[DTM.COMMENT_NODE].compile(classGen, methodGen, ihComment)
: ihComment;
// This DOM-type is not in use - default: process next node
targets[DTM.CDATA_SECTION_NODE] = ihLoop;
// This DOM-type is not in use - default: process next node
targets[DTM.DOCUMENT_FRAGMENT_NODE] = ihLoop;
// This DOM-type is not in use - default: process next node
targets[DTM.DOCUMENT_TYPE_NODE] = ihLoop;
// This DOM-type is not in use - default: process next node
targets[DTM.ENTITY_NODE] = ihLoop;
// This DOM-type is not in use - default: process next node
targets[DTM.ENTITY_REFERENCE_NODE] = ihLoop;
// This DOM-type is not in use - default: process next node
targets[DTM.NOTATION_NODE] = ihLoop;
// Now compile test sequences for various match patterns:
for (int i = DTM.NTYPES; i < targets.length; i++) {
final TestSeq testSeq = _testSeq[i];
// Jump straight to namespace tests ?
if ((testSeq == null) || (isNamespace[i])) {
if (isAttribute[i])
targets[i] = attrNamespaceHandle;
else
targets[i] = elemNamespaceHandle;
}
// Match on node type
else {
if (isAttribute[i])
targets[i] = testSeq.compile(classGen, methodGen,
attrNamespaceHandle);
else
targets[i] = testSeq.compile(classGen, methodGen,
elemNamespaceHandle);
}
}
if (ilKey != null) body.insert(ilKey);
// Append first code in applyTemplates() - get type of current node
final int getType = cpg.addInterfaceMethodref(DOM_INTF,
"getExpandedTypeID",
"(I)I");
body.append(methodGen.loadDOM());
body.append(new ILOAD(_currentIndex));
body.append(new INVOKEINTERFACE(getType, 2));