FileDocCategorySizeDatePackage
Stylesheet.javaAPI DocJava SE 6 API45182Tue Jun 10 00:22:30 BST 2008com.sun.org.apache.xalan.internal.xsltc.compiler

Stylesheet

public final class Stylesheet extends SyntaxTreeNode
author
Jacek Ambroziak
author
Santiago Pericas-Geertsen
author
Morten Jorgensen

Fields Summary
private String
_version
XSLT version defined in the stylesheet.
private QName
_name
Internal name of this stylesheet used as a key into the symbol table.
private String
_systemId
A URI that represents the system ID for this stylesheet.
private Stylesheet
_parentStylesheet
A reference to the parent stylesheet or null if topmost.
private Vector
_globals
Contains global variables and parameters defined in the stylesheet.
private Boolean
_hasLocalParams
Used to cache the result returned by hasLocalParams().
private String
_className
The name of the class being generated.
private final Vector
_templates
Contains all templates defined in this stylesheet
private Vector
_allValidTemplates
Used to cache result of getAllValidTemplates(). Only set in top-level stylesheets that include/import other stylesheets.
private int
_nextModeSerial
Counter to generate unique mode suffixes.
private final Hashtable
_modes
Mapping between mode names and Mode instances.
private Mode
_defaultMode
A reference to the default Mode object.
private final Hashtable
_extensions
Mapping between extension URIs and their prefixes.
public Stylesheet
_importedFrom
Reference to the stylesheet from which this stylesheet was imported (if any).
public Stylesheet
_includedFrom
Reference to the stylesheet from which this stylesheet was included (if any).
private Vector
_includedStylesheets
Array of all the stylesheets imported or included from this one.
private int
_importPrecedence
Import precendence for this stylesheet.
private int
_minimumDescendantPrecedence
Minimum precendence of any descendant stylesheet by inclusion or importation.
private Hashtable
_keys
Mapping between key names and Key objects (needed by Key/IdPattern).
private SourceLoader
_loader
A reference to the SourceLoader set by the user (a URIResolver if the JAXP API is being used).
private boolean
_numberFormattingUsed
Flag indicating if format-number() is called.
private boolean
_simplified
Flag indicating if this is a simplified stylesheets. A template matching on "/" must be added in this case.
private boolean
_multiDocument
Flag indicating if multi-document support is needed.
private boolean
_callsNodeset
Flag indicating if nodset() is called.
private boolean
_hasIdCall
Flag indicating if id() is called.
private boolean
_templateInlining
Set to true to enable template inlining optimization.
private Output
_lastOutputElement
A reference to the last xsl:output object found in the styleshet.
private Properties
_outputProperties
Output properties for this stylesheet.
private int
_outputMethod
Output method for this stylesheet (must be set to one of the constants defined below).
public static final int
UNKNOWN_OUTPUT
public static final int
XML_OUTPUT
public static final int
HTML_OUTPUT
public static final int
TEXT_OUTPUT
Constructors Summary
Methods Summary
private voidaddDOMField(com.sun.org.apache.xalan.internal.xsltc.compiler.util.ClassGenerator classGen)

	final FieldGen fgen = new FieldGen(ACC_PUBLIC,
					   Util.getJCRefType(DOM_INTF_SIG),
					   DOM_FIELD,
					   classGen.getConstantPool());
	classGen.addField(fgen.getField());
    
public voidaddIncludedStylesheet(com.sun.org.apache.xalan.internal.xsltc.compiler.Stylesheet child)

    	if (_includedStylesheets == null) {
    	    _includedStylesheets = new Vector();
    	}
    	_includedStylesheets.addElement(child);
    
public intaddParam(com.sun.org.apache.xalan.internal.xsltc.compiler.Param param)

	_globals.addElement(param);
	return _globals.size() - 1;
    
protected voidaddPrefixMapping(java.lang.String prefix, java.lang.String uri)
Adds a single prefix mapping to this syntax tree node.

param
prefix Namespace prefix.
param
uri Namespace URI.

	if (prefix.equals(EMPTYSTRING) && uri.equals(XHTML_URI)) return;
	super.addPrefixMapping(prefix, uri);
    
private voidaddStaticField(com.sun.org.apache.xalan.internal.xsltc.compiler.util.ClassGenerator classGen, java.lang.String type, java.lang.String name)
Add a static field

        final FieldGen fgen = new FieldGen(ACC_PROTECTED|ACC_STATIC,
                                           Util.getJCRefType(type),
                                           name,
                                           classGen.getConstantPool());
        classGen.addField(fgen.getField());

    
protected voidaddTemplate(com.sun.org.apache.xalan.internal.xsltc.compiler.Template template)

        _templates.addElement(template);
    
public intaddVariable(com.sun.org.apache.xalan.internal.xsltc.compiler.Variable global)

	_globals.addElement(global);
	return _globals.size() - 1;
    
public booleancallsNodeset()

	return _callsNodeset;
    
public booleancheckForLoop(java.lang.String systemId)

	// Return true if this stylesheet includes/imports itself
	if (_systemId != null && _systemId.equals(systemId)) {
	    return true;
	}
	// Then check with any stylesheets that included/imported this one
	if (_parentStylesheet != null) 
	    return _parentStylesheet.checkForLoop(systemId);
	// Otherwise OK
	return false;
    
private voidcheckOutputMethod()
Check and set the output method

	if (_lastOutputElement != null) {
	    String method = _lastOutputElement.getOutputMethod();
	    if (method != null) {
	        if (method.equals("xml"))
	            _outputMethod = XML_OUTPUT;
	        else if (method.equals("html"))
	            _outputMethod = HTML_OUTPUT;
	        else if (method.equals("text"))
	            _outputMethod = TEXT_OUTPUT;
	    }
	}
    
private java.lang.StringcompileBuildKeys(com.sun.org.apache.xalan.internal.xsltc.compiler.util.ClassGenerator classGen)
Compile a buildKeys() method into the output class. Note that keys for the input document are created in topLevel(), not in this method. However, we still need this method to create keys for documents loaded via the XPath document() function.

	final ConstantPoolGen cpg = classGen.getConstantPool();

	final com.sun.org.apache.bcel.internal.generic.Type[] argTypes = {
	    Util.getJCRefType(DOM_INTF_SIG),
	    Util.getJCRefType(NODE_ITERATOR_SIG),
	    Util.getJCRefType(TRANSLET_OUTPUT_SIG),
	    com.sun.org.apache.bcel.internal.generic.Type.INT
	};

	final String[] argNames = {
	    DOCUMENT_PNAME, ITERATOR_PNAME, TRANSLET_OUTPUT_PNAME, "current"
	};

	final InstructionList il = new InstructionList();

	final MethodGenerator buildKeys =
	    new MethodGenerator(ACC_PUBLIC,
				com.sun.org.apache.bcel.internal.generic.Type.VOID,
				argTypes, argNames,
				"buildKeys", _className, il,
				classGen.getConstantPool());

	buildKeys.addException("com.sun.org.apache.xalan.internal.xsltc.TransletException");
	
	final Enumeration elements = elements();
	while (elements.hasMoreElements()) {
	    // xsl:key
	    final Object element = elements.nextElement();
	    if (element instanceof Key) {
		final Key key = (Key)element;
		key.translate(classGen, buildKeys);
		_keys.put(key.getName(),key);
	    }
	}
	
	il.append(RETURN);
	
	// Compute max locals + stack and add method to class
	buildKeys.stripAttributes(true);
	buildKeys.setMaxLocals();
	buildKeys.setMaxStack();
	buildKeys.removeNOPs();

	classGen.addMethod(buildKeys.getMethod());
	
	return("("+DOM_INTF_SIG+NODE_ITERATOR_SIG+TRANSLET_OUTPUT_SIG+"I)V");
    
private voidcompileConstructor(com.sun.org.apache.xalan.internal.xsltc.compiler.util.ClassGenerator classGen, com.sun.org.apache.xalan.internal.xsltc.compiler.Output output)
Compile the translet's constructor


	final ConstantPoolGen cpg = classGen.getConstantPool();
	final InstructionList il = new InstructionList();

	final MethodGenerator constructor =
	    new MethodGenerator(ACC_PUBLIC,
				com.sun.org.apache.bcel.internal.generic.Type.VOID, 
				null, null, "<init>", 
				_className, il, cpg);

	// Call the constructor in the AbstractTranslet superclass
	il.append(classGen.loadTranslet());
	il.append(new INVOKESPECIAL(cpg.addMethodref(TRANSLET_CLASS,
						     "<init>", "()V")));
	
	il.append(classGen.loadTranslet());
	il.append(new GETSTATIC(cpg.addFieldref(_className,
	                                        STATIC_NAMES_ARRAY_FIELD,
	                                        NAMES_INDEX_SIG)));
	il.append(new PUTFIELD(cpg.addFieldref(TRANSLET_CLASS,
	                                       NAMES_INDEX,
	                                       NAMES_INDEX_SIG)));
	
	il.append(classGen.loadTranslet());
	il.append(new GETSTATIC(cpg.addFieldref(_className,
	                                        STATIC_URIS_ARRAY_FIELD,
	                                        URIS_INDEX_SIG)));
	il.append(new PUTFIELD(cpg.addFieldref(TRANSLET_CLASS,
	                                       URIS_INDEX,
	                                       URIS_INDEX_SIG)));

	il.append(classGen.loadTranslet());
	il.append(new GETSTATIC(cpg.addFieldref(_className,
	                                        STATIC_TYPES_ARRAY_FIELD,
	                                        TYPES_INDEX_SIG)));
	il.append(new PUTFIELD(cpg.addFieldref(TRANSLET_CLASS,
	                                       TYPES_INDEX,
	                                       TYPES_INDEX_SIG)));

	il.append(classGen.loadTranslet());
	il.append(new GETSTATIC(cpg.addFieldref(_className,
	                                        STATIC_NAMESPACE_ARRAY_FIELD,
	                                        NAMESPACE_INDEX_SIG)));
	il.append(new PUTFIELD(cpg.addFieldref(TRANSLET_CLASS,
	                                       NAMESPACE_INDEX,
	                                       NAMESPACE_INDEX_SIG)));

	il.append(classGen.loadTranslet());
        il.append(new PUSH(cpg, AbstractTranslet.CURRENT_TRANSLET_VERSION));
	il.append(new PUTFIELD(cpg.addFieldref(TRANSLET_CLASS,
	                                       TRANSLET_VERSION_INDEX,
	                                       TRANSLET_VERSION_INDEX_SIG)));
	
	if (_hasIdCall) {
	    il.append(classGen.loadTranslet());
	    il.append(new PUSH(cpg, Boolean.TRUE));
	    il.append(new PUTFIELD(cpg.addFieldref(TRANSLET_CLASS,
					           HASIDCALL_INDEX,
					           HASIDCALL_INDEX_SIG)));
	}
	
	// Compile in code to set the output configuration from <xsl:output>
	if (output != null) {
	    // Set all the output settings files in the translet
	    output.translate(classGen, constructor);
	}

	// Compile default decimal formatting symbols.
	// This is an implicit, nameless xsl:decimal-format top-level element.
	if (_numberFormattingUsed)
	    DecimalFormatting.translateDefaultDFS(classGen, constructor);

	il.append(RETURN);

	constructor.stripAttributes(true);
	constructor.setMaxLocals();
	constructor.setMaxStack();
	classGen.addMethod(constructor.getMethod());
    
private voidcompileModes(com.sun.org.apache.xalan.internal.xsltc.compiler.util.ClassGenerator classGen)

	_defaultMode.compileApplyTemplates(classGen);
	final Enumeration modes = _modes.elements();
	while (modes.hasMoreElements()) {
	    final Mode mode = (Mode)modes.nextElement();
	    mode.compileApplyTemplates(classGen);
	}
    
private voidcompileStaticInitializer(com.sun.org.apache.xalan.internal.xsltc.compiler.util.ClassGenerator classGen)
Compile the namesArray, urisArray and typesArray into the static initializer. They are read-only from the translet. All translet instances can share a single copy of this informtion.

	final ConstantPoolGen cpg = classGen.getConstantPool();
	final InstructionList il = new InstructionList();

	final MethodGenerator staticConst =
	    new MethodGenerator(ACC_PUBLIC|ACC_STATIC,
				com.sun.org.apache.bcel.internal.generic.Type.VOID, 
				null, null, "<clinit>", 
				_className, il, cpg);

	addStaticField(classGen, "[" + STRING_SIG, STATIC_NAMES_ARRAY_FIELD);
	addStaticField(classGen, "[" + STRING_SIG, STATIC_URIS_ARRAY_FIELD);
	addStaticField(classGen, "[I", STATIC_TYPES_ARRAY_FIELD);
	addStaticField(classGen, "[" + STRING_SIG, STATIC_NAMESPACE_ARRAY_FIELD);
        // Create fields of type char[] that will contain literal text from
        // the stylesheet.
        final int charDataFieldCount = getXSLTC().getCharacterDataCount();
        for (int i = 0; i < charDataFieldCount; i++) {
            addStaticField(classGen, STATIC_CHAR_DATA_FIELD_SIG,
                           STATIC_CHAR_DATA_FIELD+i);
        }

	// Put the names array into the translet - used for dom/translet mapping
	final Vector namesIndex = getXSLTC().getNamesIndex();
	int size = namesIndex.size();
	String[] namesArray = new String[size];
	String[] urisArray = new String[size];
	int[] typesArray = new int[size];
	
	int index;
	for (int i = 0; i < size; i++) {
	    String encodedName = (String)namesIndex.elementAt(i);
	    if ((index = encodedName.lastIndexOf(':")) > -1) {
	        urisArray[i] = encodedName.substring(0, index);
	    }
	    
	    index = index + 1;
	    if (encodedName.charAt(index) == '@") {
	    	typesArray[i] = DTM.ATTRIBUTE_NODE;
	    	index++;
	    } else if (encodedName.charAt(index) == '?") {
	    	typesArray[i] = DTM.NAMESPACE_NODE;
	    	index++;
	    } else {
	        typesArray[i] = DTM.ELEMENT_NODE;
	    }
	    
	    if (index == 0) {
	        namesArray[i] = encodedName;
	    }
	    else {
	        namesArray[i] = encodedName.substring(index);
	    }	    
	}
	
	il.append(new PUSH(cpg, size));
	il.append(new ANEWARRAY(cpg.addClass(STRING)));		

	for (int i = 0; i < size; i++) {
	    final String name = namesArray[i];
	    il.append(DUP);
	    il.append(new PUSH(cpg, i));
	    il.append(new PUSH(cpg, name));
	    il.append(AASTORE);
	}
	il.append(new PUTSTATIC(cpg.addFieldref(_className,
					       STATIC_NAMES_ARRAY_FIELD,
					       NAMES_INDEX_SIG)));

	il.append(new PUSH(cpg, size));
	il.append(new ANEWARRAY(cpg.addClass(STRING)));		

	for (int i = 0; i < size; i++) {
	    final String uri = urisArray[i];
	    il.append(DUP);
	    il.append(new PUSH(cpg, i));
	    il.append(new PUSH(cpg, uri));
	    il.append(AASTORE);
	}
	il.append(new PUTSTATIC(cpg.addFieldref(_className,
					       STATIC_URIS_ARRAY_FIELD,
					       URIS_INDEX_SIG)));

	il.append(new PUSH(cpg, size));
	il.append(new NEWARRAY(BasicType.INT));		

	for (int i = 0; i < size; i++) {
	    final int nodeType = typesArray[i];
	    il.append(DUP);
	    il.append(new PUSH(cpg, i));
	    il.append(new PUSH(cpg, nodeType));
	    il.append(IASTORE);
	}
	il.append(new PUTSTATIC(cpg.addFieldref(_className,
					       STATIC_TYPES_ARRAY_FIELD,
					       TYPES_INDEX_SIG)));

	// Put the namespace names array into the translet
	final Vector namespaces = getXSLTC().getNamespaceIndex();
	il.append(new PUSH(cpg, namespaces.size()));
	il.append(new ANEWARRAY(cpg.addClass(STRING)));		

	for (int i = 0; i < namespaces.size(); i++) {
	    final String ns = (String)namespaces.elementAt(i);
	    il.append(DUP);
	    il.append(new PUSH(cpg, i));
	    il.append(new PUSH(cpg, ns));
	    il.append(AASTORE);
	}
	il.append(new PUTSTATIC(cpg.addFieldref(_className,
					       STATIC_NAMESPACE_ARRAY_FIELD,
					       NAMESPACE_INDEX_SIG)));

        // Grab all the literal text in the stylesheet and put it in a char[]
        final int charDataCount = getXSLTC().getCharacterDataCount();
        final int toCharArray = cpg.addMethodref(STRING, "toCharArray", "()[C");
        for (int i = 0; i < charDataCount; i++) {
            il.append(new PUSH(cpg, getXSLTC().getCharacterData(i)));
            il.append(new INVOKEVIRTUAL(toCharArray));
            il.append(new PUTSTATIC(cpg.addFieldref(_className,
                                               STATIC_CHAR_DATA_FIELD+i,
                                               STATIC_CHAR_DATA_FIELD_SIG)));
        }

	il.append(RETURN);

	staticConst.stripAttributes(true);
	staticConst.setMaxLocals();
	staticConst.setMaxStack();
	classGen.addMethod(staticConst.getMethod());
    	
    
private java.lang.StringcompileTopLevel(com.sun.org.apache.xalan.internal.xsltc.compiler.util.ClassGenerator classGen)
Compile a topLevel() method into the output class. This method is called from transform() to handle all non-template top-level elements. Returns the signature of the topLevel() method. Global variables/params and keys are first sorted to resolve dependencies between them. The XSLT 1.0 spec does not allow a key to depend on a variable. However, for compatibility with Xalan interpretive, that type of dependency is allowed. Note also that the buildKeys() method is still generated as it is used by the LoadDocument class, but it no longer called from transform().


	final ConstantPoolGen cpg = classGen.getConstantPool();

	final com.sun.org.apache.bcel.internal.generic.Type[] argTypes = {
	    Util.getJCRefType(DOM_INTF_SIG),
	    Util.getJCRefType(NODE_ITERATOR_SIG),
	    Util.getJCRefType(TRANSLET_OUTPUT_SIG)
	};

	final String[] argNames = {
	    DOCUMENT_PNAME, ITERATOR_PNAME, TRANSLET_OUTPUT_PNAME
	};

	final InstructionList il = new InstructionList();

	final MethodGenerator toplevel =
	    new MethodGenerator(ACC_PUBLIC,
				com.sun.org.apache.bcel.internal.generic.Type.VOID,
				argTypes, argNames,
				"topLevel", _className, il,
				classGen.getConstantPool());

	toplevel.addException("com.sun.org.apache.xalan.internal.xsltc.TransletException");

	// Define and initialize 'current' variable with the root node
	final LocalVariableGen current = 
	    toplevel.addLocalVariable("current",
				    com.sun.org.apache.bcel.internal.generic.Type.INT,
				    il.getEnd(), null);

	final int setFilter = cpg.addInterfaceMethodref(DOM_INTF,
			       "setFilter",
			       "(Lcom/sun/org/apache/xalan/internal/xsltc/StripFilter;)V");

	il.append(new PUSH(cpg, DTM.ROOT_NODE));
	il.append(new ISTORE(current.getIndex()));

        // Create a new list containing variables/params + keys
        Vector varDepElements = new Vector(_globals);
	Enumeration elements = elements();
	while (elements.hasMoreElements()) {
	    final Object element = elements.nextElement();
	    if (element instanceof Key) {
                varDepElements.add(element);
	    }
	}

        // Determine a partial order for the variables/params and keys
	varDepElements = resolveDependencies(varDepElements);

        // Translate vars/params and keys in the right order
	final int count = varDepElements.size();
	for (int i = 0; i < count; i++) {
	    final TopLevelElement tle = (TopLevelElement) varDepElements.elementAt(i);            
	    tle.translate(classGen, toplevel);            
	    if (tle instanceof Key) {
		final Key key = (Key) tle;
		_keys.put(key.getName(), key);
	    }
	}

	// Compile code for other top-level elements
	Vector whitespaceRules = new Vector();
        elements = elements();
	while (elements.hasMoreElements()) {
	    final Object element = elements.nextElement();
	    // xsl:decimal-format
	    if (element instanceof DecimalFormatting) {
		((DecimalFormatting)element).translate(classGen,toplevel);
	    }
	    // xsl:strip/preserve-space
	    else if (element instanceof Whitespace) {
		whitespaceRules.addAll(((Whitespace)element).getRules());
	    }
	}

	// Translate all whitespace strip/preserve rules
	if (whitespaceRules.size() > 0) {
	    Whitespace.translateRules(whitespaceRules,classGen);
	}

	if (classGen.containsMethod(STRIP_SPACE, STRIP_SPACE_PARAMS) != null) {
	    il.append(toplevel.loadDOM());
	    il.append(classGen.loadTranslet());
	    il.append(new INVOKEINTERFACE(setFilter, 2));
	}

	il.append(RETURN);

	// Compute max locals + stack and add method to class
	toplevel.stripAttributes(true);
	toplevel.setMaxLocals();
	toplevel.setMaxStack();
	toplevel.removeNOPs();

	classGen.addMethod(toplevel.getMethod());
	
	return("("+DOM_INTF_SIG+NODE_ITERATOR_SIG+TRANSLET_OUTPUT_SIG+")V");
    
private voidcompileTransform(com.sun.org.apache.xalan.internal.xsltc.compiler.util.ClassGenerator classGen)
Compile transform() into the output class. This method is used to initialize global variables and global parameters. The current node is set to be the document's root node.

	final ConstantPoolGen cpg = classGen.getConstantPool();

	/* 
	 * Define the the method transform with the following signature:
	 * void transform(DOM, NodeIterator, HandlerBase)
	 */
	final com.sun.org.apache.bcel.internal.generic.Type[] argTypes = 
	    new com.sun.org.apache.bcel.internal.generic.Type[3];
	argTypes[0] = Util.getJCRefType(DOM_INTF_SIG);
	argTypes[1] = Util.getJCRefType(NODE_ITERATOR_SIG);
	argTypes[2] = Util.getJCRefType(TRANSLET_OUTPUT_SIG);

	final String[] argNames = new String[3];
	argNames[0] = DOCUMENT_PNAME;
	argNames[1] = ITERATOR_PNAME;
	argNames[2] = TRANSLET_OUTPUT_PNAME;

	final InstructionList il = new InstructionList();
	final MethodGenerator transf =
	    new MethodGenerator(ACC_PUBLIC,
				com.sun.org.apache.bcel.internal.generic.Type.VOID,
				argTypes, argNames,
				"transform",
				_className,
				il,
				classGen.getConstantPool());
	transf.addException("com.sun.org.apache.xalan.internal.xsltc.TransletException");

	// Define and initialize current with the root node
	final LocalVariableGen current = 
	    transf.addLocalVariable("current",
				    com.sun.org.apache.bcel.internal.generic.Type.INT,
				    il.getEnd(), null);
	final String applyTemplatesSig = classGen.getApplyTemplatesSig();
	final int applyTemplates = cpg.addMethodref(getClassName(),
						    "applyTemplates",
						    applyTemplatesSig);
	final int domField = cpg.addFieldref(getClassName(),
					     DOM_FIELD,
					     DOM_INTF_SIG);

	// push translet for PUTFIELD
	il.append(classGen.loadTranslet());
	// prepare appropriate DOM implementation
	
	if (isMultiDocument()) {
	    il.append(new NEW(cpg.addClass(MULTI_DOM_CLASS)));
	    il.append(DUP);
	}
	
	il.append(classGen.loadTranslet());
	il.append(transf.loadDOM());
	il.append(new INVOKEVIRTUAL(cpg.addMethodref(TRANSLET_CLASS,
						     "makeDOMAdapter",
						     "("+DOM_INTF_SIG+")"+
						     DOM_ADAPTER_SIG)));
	// DOMAdapter is on the stack

	if (isMultiDocument()) {
	    final int init = cpg.addMethodref(MULTI_DOM_CLASS,
					      "<init>",
					      "("+DOM_INTF_SIG+")V");
	    il.append(new INVOKESPECIAL(init));
	    // MultiDOM is on the stack
	}
	
	//store to _dom variable
	il.append(new PUTFIELD(domField));

	// continue with globals initialization
	il.append(new PUSH(cpg, DTM.ROOT_NODE));
	il.append(new ISTORE(current.getIndex()));

	// Transfer the output settings to the output post-processor
	il.append(classGen.loadTranslet());
	il.append(transf.loadHandler());
	final int index = cpg.addMethodref(TRANSLET_CLASS,
					   "transferOutputSettings",
					   "("+OUTPUT_HANDLER_SIG+")V");
	il.append(new INVOKEVIRTUAL(index));

        /*
         * Compile buildKeys() method. Note that this method is not 
         * invoked here as keys for the input document are now created
         * in topLevel(). However, this method is still needed by the
         * LoadDocument class.
         */        
        final String keySig = compileBuildKeys(classGen);
        final int keyIdx = cpg.addMethodref(getClassName(),
                                               "buildKeys", keySig);
                
        // Look for top-level elements that need handling
	final Enumeration toplevel = elements();
	if (_globals.size() > 0 || toplevel.hasMoreElements()) {
	    // Compile method for handling top-level elements
	    final String topLevelSig = compileTopLevel(classGen);
	    // Get a reference to that method
	    final int topLevelIdx = cpg.addMethodref(getClassName(),
						     "topLevel",
						     topLevelSig);
	    // Push all parameters on the stack and call topLevel()
	    il.append(classGen.loadTranslet()); // The 'this' pointer
	    il.append(classGen.loadTranslet());
	    il.append(new GETFIELD(domField));  // The DOM reference
	    il.append(transf.loadIterator());
	    il.append(transf.loadHandler());    // The output handler
	    il.append(new INVOKEVIRTUAL(topLevelIdx));
	}	

	// start document
	il.append(transf.loadHandler());
	il.append(transf.startDocument());

	// push first arg for applyTemplates
	il.append(classGen.loadTranslet());
	// push translet for GETFIELD to get DOM arg
	il.append(classGen.loadTranslet());
	il.append(new GETFIELD(domField));
	// push remaining 2 args
	il.append(transf.loadIterator());
	il.append(transf.loadHandler());
	il.append(new INVOKEVIRTUAL(applyTemplates));
	// endDocument
	il.append(transf.loadHandler());
	il.append(transf.endDocument());

	il.append(RETURN);

	// Compute max locals + stack and add method to class
	transf.stripAttributes(true);
	transf.setMaxLocals();
	transf.setMaxStack();
	transf.removeNOPs();

	classGen.addMethod(transf.getMethod());
    
public voiddisplay(int indent)

	indent(indent);
	Util.println("Stylesheet");
	displayContents(indent + IndentIncrement);
    
public voidexcludeExtensionPrefixes(com.sun.org.apache.xalan.internal.xsltc.compiler.Parser parser)

	final SymbolTable stable = parser.getSymbolTable();
    	final String excludePrefixes = getAttribute("exclude-result-prefixes");
	final String extensionPrefixes = getAttribute("extension-element-prefixes");
	
	// Exclude XSLT uri 
	stable.excludeURI(Constants.XSLT_URI);
	stable.excludeNamespaces(excludePrefixes);
	stable.excludeNamespaces(extensionPrefixes);
	extensionURI(extensionPrefixes, stable);
    
private voidextensionURI(java.lang.String prefixes, com.sun.org.apache.xalan.internal.xsltc.compiler.SymbolTable stable)
Store extension URIs

	if (prefixes != null) {
	    StringTokenizer tokens = new StringTokenizer(prefixes);
	    while (tokens.hasMoreTokens()) {
		final String prefix = tokens.nextToken();
		final String uri = lookupNamespace(prefix);
		if (uri != null) {
		    _extensions.put(uri, prefix);
		}
	    }
	}
    
public java.util.VectorgetAllValidTemplates()

        // Return templates if no imported/included stylesheets
        if (_includedStylesheets == null) {
            return _templates;
        }
        
        // Is returned value cached?
        if (_allValidTemplates == null) {
           Vector templates = new Vector();
           templates.addAll(_templates);
            int size = _includedStylesheets.size();
            for (int i = 0; i < size; i++) {
                Stylesheet included =(Stylesheet)_includedStylesheets.elementAt(i);
                templates.addAll(included.getAllValidTemplates());
            }
            //templates.addAll(_templates);

            // Cache results in top-level stylesheet only
            if (_parentStylesheet != null) {
                return templates;
            }
            _allValidTemplates = templates;
         }
        
        return _allValidTemplates;
    
public java.lang.StringgetClassName()

	return _className;
    
public intgetImportPrecedence()

	return _importPrecedence;
    
public com.sun.org.apache.xalan.internal.xsltc.compiler.OutputgetLastOutputElement()

    	return _lastOutputElement;
    
public intgetMinimumDescendantPrecedence()
Get the minimum of the precedence of this stylesheet, any stylesheet imported by this stylesheet and any include/import descendant of this stylesheet.

        if (_minimumDescendantPrecedence == -1) {
            // Start with precedence of current stylesheet as a basis.
            int min = getImportPrecedence();

            // Recursively examine all imported/included stylesheets.
            final int inclImpCount = (_includedStylesheets != null)
                                          ? _includedStylesheets.size()
                                          : 0;

            for (int i = 0; i < inclImpCount; i++) {
                int prec = ((Stylesheet)_includedStylesheets.elementAt(i))
                                              .getMinimumDescendantPrecedence();

                if (prec < min) {
                    min = prec;
                }
            }

            _minimumDescendantPrecedence = min;
        }
        return _minimumDescendantPrecedence;
    
public com.sun.org.apache.xalan.internal.xsltc.compiler.ModegetMode(com.sun.org.apache.xalan.internal.xsltc.compiler.QName modeName)

	if (modeName == null) {
	    if (_defaultMode == null) {
		_defaultMode = new Mode(null, this, Constants.EMPTYSTRING);
	    }
	    return _defaultMode;
	}
	else {
	    Mode mode = (Mode)_modes.get(modeName);
	    if (mode == null) {
		final String suffix = Integer.toString(_nextModeSerial++);
		_modes.put(modeName, mode = new Mode(modeName, this, suffix));
	    }
	    return mode;
	}
    
public java.lang.StringgetNamespace(java.lang.String prefix)

	return lookupNamespace(prefix);
    
public intgetOutputMethod()
Return the output method

    
             
       
    	return _outputMethod;
    
public java.util.PropertiesgetOutputProperties()

	return _outputProperties;
    
public com.sun.org.apache.xalan.internal.xsltc.compiler.StylesheetgetParentStylesheet()

	return _parentStylesheet;
    
public com.sun.org.apache.xalan.internal.xsltc.compiler.SourceLoadergetSourceLoader()

	return _loader;
    
public java.lang.StringgetSystemId()

	return _systemId;
    
public booleangetTemplateInlining()

	return _templateInlining;
    
public java.util.VectorgetTemplates()

	return _templates;
    
public booleanhasGlobals()
Returns true if this stylesheet has global vars or params.

	return _globals.size() > 0;
    
public booleanhasLocalParams()
Returns true if at least one template in the stylesheet has params defined. Uses the variable _hasLocalParams to cache the result.

	if (_hasLocalParams == null) {
	    Vector templates = getAllValidTemplates();
	    final int n = templates.size();
	    for (int i = 0; i < n; i++) {
		final Template template = (Template)templates.elementAt(i);
		if (template.hasParams()) {
		    _hasLocalParams = new Boolean(true);
		    return true;
		}
	    }
	    _hasLocalParams = new Boolean(false);
	    return false;
	}
	else {
	    return _hasLocalParams.booleanValue();
	}
    
public booleanisExtension(java.lang.String uri)

	return (_extensions.get(uri) != null);
    
public booleanisMultiDocument()

	return _multiDocument;
    
public booleanisSimplified()

	return(_simplified);
    
private com.sun.org.apache.xalan.internal.xsltc.compiler.QNamemakeStylesheetName(java.lang.String prefix)

	return getParser().getQName(prefix+getXSLTC().nextStylesheetSerial());
    
public voidnumberFormattingUsed()

	_numberFormattingUsed = true;
        /*
         * Fix for bug 23046, if the stylesheet is included, set the 
         * numberFormattingUsed flag to the parent stylesheet too.
         * AbstractTranslet.addDecimalFormat() will be inlined once for the
         * outer most stylesheet. 
         */ 
        Stylesheet parent = getParentStylesheet();
        if (null != parent) parent.numberFormattingUsed();        
    
public voidparseContents(com.sun.org.apache.xalan.internal.xsltc.compiler.Parser parser)
Parse the version and uri fields of the stylesheet and add an entry to the symbol table mapping the name __stylesheet_ to an instance of this class.

	final SymbolTable stable = parser.getSymbolTable();

	/*
	// Make sure the XSL version set in this stylesheet
	if ((_version == null) || (_version.equals(EMPTYSTRING))) {
	    reportError(this, parser, ErrorMsg.REQUIRED_ATTR_ERR,"version");
	}
	// Verify that the version is 1.0 and nothing else
	else if (!_version.equals("1.0")) {
	    reportError(this, parser, ErrorMsg.XSL_VERSION_ERR, _version);
	}
	*/

	// Add the implicit mapping of 'xml' to the XML namespace URI
	addPrefixMapping("xml", "http://www.w3.org/XML/1998/namespace");

	// Report and error if more than one stylesheet defined
	final Stylesheet sheet = stable.addStylesheet(_name, this);
	if (sheet != null) {
	    // Error: more that one stylesheet defined
	    ErrorMsg err = new ErrorMsg(ErrorMsg.MULTIPLE_STYLESHEET_ERR,this);
	    parser.reportError(Constants.ERROR, err);
	}

	// If this is a simplified stylesheet we must create a template that
	// grabs the root node of the input doc ( <xsl:template match="/"/> ).
	// This template needs the current element (the one passed to this
	// method) as its only child, so the Template class has a special
	// method that handles this (parseSimplified()).
	if (_simplified) {
	    stable.excludeURI(XSLT_URI);
	    Template template = new Template();
	    template.parseSimplified(this, parser);
	}
	// Parse the children of this node
	else {
	    parseOwnChildren(parser);
	}
    
public final voidparseOwnChildren(com.sun.org.apache.xalan.internal.xsltc.compiler.Parser parser)
Parse all direct children of the element.

	final Vector contents = getContents();
	final int count = contents.size();

	// We have to scan the stylesheet element's top-level elements for
	// variables and/or parameters before we parse the other elements
	for (int i = 0; i < count; i++) {
	    SyntaxTreeNode child = (SyntaxTreeNode)contents.elementAt(i);
	    if ((child instanceof VariableBase) ||
		(child instanceof NamespaceAlias)) {
		parser.getSymbolTable().setCurrentNode(child);
		child.parseContents(parser);
	    }
	}

	// Now go through all the other top-level elements...
	for (int i = 0; i < count; i++) {
	    SyntaxTreeNode child = (SyntaxTreeNode)contents.elementAt(i);
	    if (!(child instanceof VariableBase) && 
		!(child instanceof NamespaceAlias)) {
		parser.getSymbolTable().setCurrentNode(child);
		child.parseContents(parser);
	    }

	    // All template code should be compiled as methods if the
	    // <xsl:apply-imports/> element was ever used in this stylesheet
	    if (!_templateInlining && (child instanceof Template)) {
		Template template = (Template)child;
		String name = "template$dot$" + template.getPosition();
		template.setName(parser.getQName(name));
	    }
	}
    
private voidpeepHoleOptimization(com.sun.org.apache.xalan.internal.xsltc.compiler.util.MethodGenerator methodGen)
Peephole optimization: Remove sequences of [ALOAD, POP].

	final String pattern = "`aload'`pop'`instruction'";
	final InstructionList il = methodGen.getInstructionList();
	final InstructionFinder find = new InstructionFinder(il);
	for(Iterator iter=find.search(pattern); iter.hasNext(); ) {
	    InstructionHandle[] match = (InstructionHandle[])iter.next();
	    try {
		il.delete(match[0], match[1]);
	    } 
	    catch (TargetLostException e) {
            	// TODO: move target down into the list
            }
	}
    
public voidprocessModes()

	if (_defaultMode == null)
	    _defaultMode = new Mode(null, this, Constants.EMPTYSTRING);
	_defaultMode.processPatterns(_keys);
	final Enumeration modes = _modes.elements();
	while (modes.hasMoreElements()) {
	    final Mode mode = (Mode)modes.nextElement();
	    mode.processPatterns(_keys);
	}
    
private java.util.VectorresolveDependencies(java.util.Vector input)
This method returns a vector with variables/params and keys in the order in which they are to be compiled for initialization. The order is determined by analyzing the dependencies between them. The XSLT 1.0 spec does not allow a key to depend on a variable. However, for compatibility with Xalan interpretive, that type of dependency is allowed and, therefore, consider to determine the partial order.

	/* DEBUG CODE - INGORE 
	for (int i = 0; i < input.size(); i++) {
	    final TopLevelElement e = (TopLevelElement) input.elementAt(i);
	    System.out.println("e = " + e + " depends on:");
            Vector dep = e.getDependencies();
            for (int j = 0; j < (dep != null ? dep.size() : 0); j++) {
                System.out.println("\t" + dep.elementAt(j));
            }
	}
	System.out.println("=================================");	
        */

	Vector result = new Vector();
	while (input.size() > 0) {
	    boolean changed = false;
	    for (int i = 0; i < input.size(); ) {
		final TopLevelElement vde = (TopLevelElement) input.elementAt(i);
		final Vector dep = vde.getDependencies();
		if (dep == null || result.containsAll(dep)) {
		    result.addElement(vde);
		    input.remove(i);
		    changed = true;
		}
		else {
		    i++;
		}
	    }

	    // If nothing was changed in this pass then we have a circular ref
	    if (!changed) {
		ErrorMsg err = new ErrorMsg(ErrorMsg.CIRCULAR_VARIABLE_ERR,
					    input.toString(), this);
		getParser().reportError(Constants.ERROR, err);
		return(result);
	    }
	}

	/* DEBUG CODE - INGORE 
	System.out.println("=================================");
	for (int i = 0; i < result.size(); i++) {
	    final TopLevelElement e = (TopLevelElement) result.elementAt(i);
	    System.out.println("e = " + e);
	}
        */

	return result;
    
public voidsetCallsNodeset(boolean flag)

	if (flag) setMultiDocument(flag);
	_callsNodeset = flag;
    
public voidsetHasIdCall(boolean flag)

        _hasIdCall = flag;
    
public voidsetImportPrecedence(int precedence)

	// Set import precedence for this stylesheet
	_importPrecedence = precedence;

	// Set import precedence for all included stylesheets
	final Enumeration elements = elements();
	while (elements.hasMoreElements()) {
	    SyntaxTreeNode child = (SyntaxTreeNode)elements.nextElement();
	    if (child instanceof Include) {
		Stylesheet included = ((Include)child).getIncludedStylesheet();
		if (included != null && included._includedFrom == this) {
		    included.setImportPrecedence(precedence);
		}
	    }
	}

	// Set import precedence for the stylesheet that imported this one
	if (_importedFrom != null) {
	    if (_importedFrom.getImportPrecedence() < precedence) {
		final Parser parser = getParser();
		final int nextPrecedence = parser.getNextImportPrecedence();
		_importedFrom.setImportPrecedence(nextPrecedence);
	    }
	}
	// Set import precedence for the stylesheet that included this one
	else if (_includedFrom != null) {
	    if (_includedFrom.getImportPrecedence() != precedence)
		_includedFrom.setImportPrecedence(precedence);
	}
    
public voidsetImportingStylesheet(com.sun.org.apache.xalan.internal.xsltc.compiler.Stylesheet parent)

	_importedFrom = parent;
	parent.addIncludedStylesheet(this);
    
public voidsetIncludingStylesheet(com.sun.org.apache.xalan.internal.xsltc.compiler.Stylesheet parent)

	_includedFrom = parent;
	parent.addIncludedStylesheet(this);
    
public voidsetMultiDocument(boolean flag)

	
	_multiDocument = flag;
    
public voidsetOutputProperties(java.util.Properties props)

	_outputProperties = props;
    
public voidsetOutputProperty(java.lang.String key, java.lang.String value)

	if (_outputProperties == null) {
	    _outputProperties = new Properties();
	}
	_outputProperties.setProperty(key, value);
    
public voidsetParentStylesheet(com.sun.org.apache.xalan.internal.xsltc.compiler.Stylesheet parent)

	_parentStylesheet = parent;
    
public voidsetParser(com.sun.org.apache.xalan.internal.xsltc.compiler.Parser parser)

	super.setParser(parser);
	_name = makeStylesheetName("__stylesheet_");
    
public voidsetSimplified()

	_simplified = true;
    
public voidsetSourceLoader(com.sun.org.apache.xalan.internal.xsltc.compiler.SourceLoader loader)

	_loader = loader;
    
public voidsetSystemId(java.lang.String systemId)

        if (systemId != null) {
            _systemId = SystemIDResolver.getAbsoluteURI(systemId);
        }
    
public voidsetTemplateInlining(boolean flag)

	_templateInlining = flag;
    
public voidtranslate(com.sun.org.apache.xalan.internal.xsltc.compiler.util.ClassGenerator classGen, com.sun.org.apache.xalan.internal.xsltc.compiler.util.MethodGenerator methodGen)
Translate the stylesheet into JVM bytecodes.

	translate();
    
public voidtranslate()
Translate the stylesheet into JVM bytecodes.

	_className = getXSLTC().getClassName();

	// Define a new class by extending TRANSLET_CLASS
	final ClassGenerator classGen =
	    new ClassGenerator(_className,
			       TRANSLET_CLASS,
			       Constants.EMPTYSTRING,
			       ACC_PUBLIC | ACC_SUPER,
			       null, this);
	
	addDOMField(classGen);

	// Compile transform() to initialize parameters, globals & output
	// and run the transformation
	compileTransform(classGen);

	// Translate all non-template elements and filter out all templates
	final Enumeration elements = elements();
	while (elements.hasMoreElements()) {
	    Object element = elements.nextElement();
	    // xsl:template
	    if (element instanceof Template) {
		// Separate templates by modes
		final Template template = (Template)element;
		//_templates.addElement(template);
		getMode(template.getModeName()).addTemplate(template);
	    }
	    // xsl:attribute-set
	    else if (element instanceof AttributeSet) {
		((AttributeSet)element).translate(classGen, null);
	    }
	    else if (element instanceof Output) {
		// save the element for later to pass to compileConstructor 
		Output output = (Output)element;
		if (output.enabled()) _lastOutputElement = output;
	    }
	    else {
		// Global variables and parameters are handled elsewhere.
		// Other top-level non-template elements are ignored. Literal
		// elements outside of templates will never be output.
	    }
	}

	checkOutputMethod();
	processModes();
	compileModes(classGen);
        compileStaticInitializer(classGen);
	compileConstructor(classGen, _lastOutputElement);

	if (!getParser().errorsFound()) {
	    getXSLTC().dumpClass(classGen.getJavaClass());
	}
    
public com.sun.org.apache.xalan.internal.xsltc.compiler.util.TypetypeCheck(com.sun.org.apache.xalan.internal.xsltc.compiler.SymbolTable stable)
Type check all the children of this node.

	final int count = _globals.size();
	for (int i = 0; i < count; i++) {
	    final VariableBase var = (VariableBase)_globals.elementAt(i);
	    var.typeCheck(stable);
	}
	return typeCheckContents(stable);