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

Whitespace

public final class Whitespace extends TopLevelElement
author
Morten Jorgensen

Fields Summary
public static final int
USE_PREDICATE
public static final int
STRIP_SPACE
public static final int
PRESERVE_SPACE
public static final int
RULE_NONE
public static final int
RULE_ELEMENT
public static final int
RULE_NAMESPACE
public static final int
RULE_ALL
private String
_elementList
private int
_action
private int
_importPrecedence
Constructors Summary
Methods Summary
private static voidcompileDefault(int defaultAction, com.sun.org.apache.xalan.internal.xsltc.compiler.util.ClassGenerator classGen)
Compiles the predicate method

	final ConstantPoolGen cpg = classGen.getConstantPool();
	final InstructionList il = new InstructionList();
	final XSLTC xsltc = classGen.getParser().getXSLTC();

	// private boolean Translet.stripSpace(int type) - cannot be static
	final MethodGenerator stripSpace =
	    new MethodGenerator(ACC_PUBLIC | ACC_FINAL ,
			com.sun.org.apache.bcel.internal.generic.Type.BOOLEAN, 
			new com.sun.org.apache.bcel.internal.generic.Type[] {
			    Util.getJCRefType(DOM_INTF_SIG),
			    com.sun.org.apache.bcel.internal.generic.Type.INT,
			    com.sun.org.apache.bcel.internal.generic.Type.INT
			},
			new String[] { "dom","node","type" },
			"stripSpace",classGen.getClassName(),il,cpg);

	classGen.addInterface("com/sun/org/apache/xalan/internal/xsltc/StripFilter");

	if (defaultAction == STRIP_SPACE)
	    il.append(ICONST_1);
	else
	    il.append(ICONST_0);
	il.append(IRETURN);

	stripSpace.stripAttributes(true);
	stripSpace.setMaxLocals();
	stripSpace.setMaxStack();
	stripSpace.removeNOPs();

	classGen.addMethod(stripSpace.getMethod());
    
private static voidcompilePredicate(java.util.Vector rules, int defaultAction, com.sun.org.apache.xalan.internal.xsltc.compiler.util.ClassGenerator classGen)
Compiles the predicate method

	final ConstantPoolGen cpg = classGen.getConstantPool();
	final InstructionList il = new InstructionList();
	final XSLTC xsltc = classGen.getParser().getXSLTC();

	// private boolean Translet.stripSpace(int type) - cannot be static
	final MethodGenerator stripSpace =
	    new MethodGenerator(ACC_PUBLIC | ACC_FINAL ,
			com.sun.org.apache.bcel.internal.generic.Type.BOOLEAN, 
			new com.sun.org.apache.bcel.internal.generic.Type[] {
			    Util.getJCRefType(DOM_INTF_SIG),
			    com.sun.org.apache.bcel.internal.generic.Type.INT,
			    com.sun.org.apache.bcel.internal.generic.Type.INT
			},
			new String[] { "dom","node","type" },
			"stripSpace",classGen.getClassName(),il,cpg);

	classGen.addInterface("com/sun/org/apache/xalan/internal/xsltc/StripFilter");

	final int paramDom = stripSpace.getLocalIndex("dom");
	final int paramCurrent = stripSpace.getLocalIndex("node");
	final int paramType = stripSpace.getLocalIndex("type");

	BranchHandle strip[] = new BranchHandle[rules.size()];
	BranchHandle preserve[] = new BranchHandle[rules.size()];
	int sCount = 0;
	int pCount = 0;

	// Traverse all strip/preserve rules
	for (int i = 0; i<rules.size(); i++) {
	    // Get the next rule in the prioritised list
	    WhitespaceRule rule = (WhitespaceRule)rules.elementAt(i);

	    // Returns the namespace for a node in the DOM
	    final int gns = cpg.addInterfaceMethodref(DOM_INTF,
						      "getNamespaceName",
						      "(I)Ljava/lang/String;");

	    final int strcmp = cpg.addMethodref("java/lang/String",
						"compareTo",
						"(Ljava/lang/String;)I");

	    // Handle elements="ns:*" type rule
	    if (rule.getStrength() == RULE_NAMESPACE) {
		il.append(new ALOAD(paramDom));
		il.append(new ILOAD(paramCurrent));
		il.append(new INVOKEINTERFACE(gns,2));
		il.append(new PUSH(cpg, rule.getNamespace()));
		il.append(new INVOKEVIRTUAL(strcmp));
		il.append(ICONST_0);

		if (rule.getAction() == STRIP_SPACE) {
		    strip[sCount++] = il.append(new IF_ICMPEQ(null));
		}
		else {
		    preserve[pCount++] = il.append(new IF_ICMPEQ(null));
		}
	    }
	    // Handle elements="ns:el" type rule
	    else if (rule.getStrength() == RULE_ELEMENT) {
		// Create the QName for the element
		final Parser parser = classGen.getParser();
		QName qname;
		if (rule.getNamespace() != Constants.EMPTYSTRING )
		    qname = parser.getQName(rule.getNamespace(), null,
					    rule.getElement());
		else
		    qname = parser.getQName(rule.getElement());

		// Register the element.
		final int elementType = xsltc.registerElement(qname);
		il.append(new ILOAD(paramType));
		il.append(new PUSH(cpg, elementType));

		// Compare current node type with wanted element type
		if (rule.getAction() == STRIP_SPACE)
		    strip[sCount++] = il.append(new IF_ICMPEQ(null));
		else
		    preserve[pCount++] = il.append(new IF_ICMPEQ(null));
	    }
	}

	if (defaultAction == STRIP_SPACE) {
	    compileStripSpace(strip, sCount, il);
	    compilePreserveSpace(preserve, pCount, il);
	}
	else {
	    compilePreserveSpace(preserve, pCount, il);
	    compileStripSpace(strip, sCount, il);
	}

	stripSpace.stripAttributes(true);
	stripSpace.setMaxLocals();
	stripSpace.setMaxStack();
	stripSpace.removeNOPs();

	classGen.addMethod(stripSpace.getMethod());
    
public static voidcompilePreserveSpace(com.sun.org.apache.bcel.internal.generic.BranchHandle[] preserve, int pCount, com.sun.org.apache.bcel.internal.generic.InstructionList il)

	final InstructionHandle target = il.append(ICONST_0);
	il.append(IRETURN);
	for (int i = 0; i < pCount; i++) {
	    preserve[i].setTarget(target);
	}
    
public static voidcompileStripSpace(com.sun.org.apache.bcel.internal.generic.BranchHandle[] strip, int sCount, com.sun.org.apache.bcel.internal.generic.InstructionList il)

	final InstructionHandle target = il.append(ICONST_1);
	il.append(IRETURN);
	for (int i = 0; i < sCount; i++) {
	    strip[i].setTarget(target);
	}
    
private static com.sun.org.apache.xalan.internal.xsltc.compiler.Whitespace$WhitespaceRulefindContradictingRule(java.util.Vector rules, com.sun.org.apache.xalan.internal.xsltc.compiler.Whitespace$WhitespaceRule rule)
Scans through the rules vector and looks for a rule of higher priority that contradicts the current rule.

	for (int i = 0; i < rules.size(); i++) {
	    // Get the next rule in the prioritized list
	    WhitespaceRule currentRule = (WhitespaceRule)rules.elementAt(i);
	    // We only consider rules with higher priority
	    if (currentRule == rule) {
		return null;
	    }
	    
	    /*
	     * See if there is a contradicting rule with higher priority.
	     * If the rules has the same action then this rule is redundant,
	     * if they have different action then this rule will never win.
	     */
	    switch (currentRule.getStrength()) {
	    case RULE_ALL:
		return currentRule;
		
	    case RULE_ELEMENT:
		if (!rule.getElement().equals(currentRule.getElement())) {
		    break;
		}
		// intentional fall-through
	    case RULE_NAMESPACE:
		if (rule.getNamespace().equals(currentRule.getNamespace())) {
		    return currentRule;
		}
		break;
	    }
	}
	return null;
    
public java.util.VectorgetRules()
De-tokenize the elements listed in the 'elements' attribute and instanciate a set of strip/preserve rules.

	final Vector rules = new Vector();
	// Go through each element and instanciate strip/preserve-object
	final StringTokenizer list = new StringTokenizer(_elementList);
	while (list.hasMoreElements()) {
	    rules.add(new WhitespaceRule(_action,
					 list.nextToken(),
					 _importPrecedence));
	}
	return rules;
    
public voidparseContents(com.sun.org.apache.xalan.internal.xsltc.compiler.Parser parser)
Parse the attributes of the xsl:strip/preserve-space element. The element should have not contents (ignored if any).

        // Determine if this is an xsl:strip- or preserve-space element
        _action = _qname.getLocalPart().endsWith("strip-space") 
            ? STRIP_SPACE : PRESERVE_SPACE;

        // Determine the import precedence
        _importPrecedence = parser.getCurrentImportPrecedence();

        // Get the list of elements to strip/preserve
        _elementList = getAttribute("elements");
        if (_elementList == null || _elementList.length() == 0) {
            reportError(this, parser, ErrorMsg.REQUIRED_ATTR_ERR, "elements");
            return;
        }

        final SymbolTable stable = parser.getSymbolTable();
        StringTokenizer list = new StringTokenizer(_elementList);
        StringBuffer elements = new StringBuffer(Constants.EMPTYSTRING);

        while (list.hasMoreElements()) {
            String token = list.nextToken();
            String prefix;
            String namespace;
            int col = token.indexOf(':");

            if (col != -1) {
                namespace = lookupNamespace(token.substring(0,col));
                if (namespace != null) {
                    elements.append(namespace+":"+
                                    token.substring(col+1,token.length()));
                } else {
                    elements.append(token);
                }
            } else {
                elements.append(token);
            }

            if (list.hasMoreElements())
                elements.append(" ");
        }
        _elementList = elements.toString();
    
private static intpartition(java.util.Vector rules, int p, int r)
Used with quicksort method above

	final WhitespaceRule x = (WhitespaceRule)rules.elementAt((p+r) >>> 1);
	int i = p - 1, j = r + 1;
	while (true) {
	    while (x.compareTo((WhitespaceRule)rules.elementAt(--j)) < 0) {
	    }
	    while (x.compareTo((WhitespaceRule)rules.elementAt(++i)) > 0) {
	    }
	    if (i < j) {
		final WhitespaceRule tmp = (WhitespaceRule)rules.elementAt(i);
		rules.setElementAt(rules.elementAt(j), i);
		rules.setElementAt(tmp, j);
	    }
	    else {
		return j;
	    }
	}
    
private static intprioritizeRules(java.util.Vector rules)
Orders a set or rules by priority, removes redundant rules and rules that are shadowed by stronger, contradicting rules.

	WhitespaceRule currentRule;
	int defaultAction = PRESERVE_SPACE;

	// Sort all rules with regard to priority
	quicksort(rules, 0, rules.size()-1);

	// Check if there are any "xsl:strip-space" elements at all.
	// If there are no xsl:strip elements we can ignore all xsl:preserve
	// elements and signal that all whitespaces should be preserved
	boolean strip = false;
	for (int i = 0; i < rules.size(); i++) {
	    currentRule = (WhitespaceRule)rules.elementAt(i);
	    if (currentRule.getAction() == STRIP_SPACE) {
		strip = true;
	    }
	}
	// Return with default action: PRESERVE_SPACE
	if (!strip) {
	    rules.removeAllElements();
	    return PRESERVE_SPACE;
	}

	// Remove all rules that are contradicted by rules with higher priority
	for (int idx = 0; idx < rules.size(); ) {
	    currentRule = (WhitespaceRule)rules.elementAt(idx);
	
	    // Remove this single rule if it has no purpose
	    if (findContradictingRule(rules,currentRule) != null) {
		rules.remove(idx);
	    }
	    else {
		// Remove all following rules if this one overrides all
		if (currentRule.getStrength() == RULE_ALL) {
		    defaultAction = currentRule.getAction();
		    for (int i = idx; i < rules.size(); i++) {
			rules.removeElementAt(i);
		    }
		}
		// Skip to next rule (there might not be any)...
		idx++;
	    }
	}

	// The rules vector could be empty if first rule has strength RULE_ALL
	if (rules.size() == 0) {
	    return defaultAction;
	}

	// Now work backwards and strip away all rules that have the same
	// action as the default rule (no reason the check them at the end).
	do {
	    currentRule = (WhitespaceRule)rules.lastElement();
	    if (currentRule.getAction() == defaultAction) {
		rules.removeElementAt(rules.size() - 1);
	    }
	    else {
		break;
	    }
	} while (rules.size() > 0);
	
	// Signal that whitespace detection predicate must be used.
	return defaultAction;
    
private static voidquicksort(java.util.Vector rules, int p, int r)
Sorts a range of rules with regard to PRIORITY only

	while (p < r) {
	    final int q = partition(rules, p, r);
	    quicksort(rules, p, q);
	    p = q + 1;
	}
    
public voidtranslate(com.sun.org.apache.xalan.internal.xsltc.compiler.util.ClassGenerator classGen, com.sun.org.apache.xalan.internal.xsltc.compiler.util.MethodGenerator methodGen)
This method should not produce any code

    
public static inttranslateRules(java.util.Vector rules, com.sun.org.apache.xalan.internal.xsltc.compiler.util.ClassGenerator classGen)
Takes a vector of WhitespaceRule objects and generates a predicate method. This method returns the translets default action for handling whitespace text-nodes: - USE_PREDICATE (run the method generated by this method) - STRIP_SPACE (always strip whitespace text-nodes) - PRESERVE_SPACE (always preserve whitespace text-nodes)

	// Get the core rules in prioritized order
	final int defaultAction = prioritizeRules(rules);
	// The rules vector may be empty after prioritising
	if (rules.size() == 0) {
	    compileDefault(defaultAction,classGen);
	    return defaultAction;
	}
	// Now - create a predicate method and sequence through rules...
	compilePredicate(rules, defaultAction, classGen);
	// Return with the translets required action (
	return USE_PREDICATE;
    
public com.sun.org.apache.xalan.internal.xsltc.compiler.util.TypetypeCheck(com.sun.org.apache.xalan.internal.xsltc.compiler.SymbolTable stable)
Type-check contents/attributes - nothing to do...

	return Type.Void; // We don't return anything.