FileDocCategorySizeDatePackage
FilterParentPath.javaAPI DocJava SE 6 API6274Tue Jun 10 00:22:28 BST 2008com.sun.org.apache.xalan.internal.xsltc.compiler

FilterParentPath

public final class FilterParentPath extends Expression
author
Jacek Ambroziak
author
Santiago Pericas-Geertsen

Fields Summary
private Expression
_filterExpr
private Expression
_path
private boolean
_hasDescendantAxis
Constructors Summary
public FilterParentPath(Expression filterExpr, Expression path)


         
	(_path = path).setParent(this);
	(_filterExpr = filterExpr).setParent(this);
    
Methods Summary
public voidsetDescendantAxis()

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

	super.setParser(parser);
	_filterExpr.setParser(parser);
	_path.setParser(parser);
    
public java.lang.StringtoString()

	return "FilterParentPath(" + _filterExpr + ", " + _path + ')";
    
public voidtranslate(com.sun.org.apache.xalan.internal.xsltc.compiler.util.ClassGenerator classGen, com.sun.org.apache.xalan.internal.xsltc.compiler.util.MethodGenerator methodGen)

	final ConstantPoolGen cpg = classGen.getConstantPool();
	final InstructionList il = methodGen.getInstructionList();
	// Create new StepIterator
	final int initSI = cpg.addMethodref(STEP_ITERATOR_CLASS,
					    "<init>",
					    "("
					    +NODE_ITERATOR_SIG
					    +NODE_ITERATOR_SIG
					    +")V");

        // Backwards branches are prohibited if an uninitialized object is
        // on the stack by section 4.9.4 of the JVM Specification, 2nd Ed.
        // We don't know whether this code might contain backwards branches,
        // so we mustn't create the new object until after we've created
        // the suspect arguments to its constructor.  Instead we calculate
        // the values of the arguments to the constructor first, store them
        // in temporary variables, create the object and reload the
        // arguments from the temporaries to avoid the problem.

	// Recursively compile 2 iterators
	_filterExpr.translate(classGen, methodGen);
        LocalVariableGen filterTemp =
                methodGen.addLocalVariable("filter_parent_path_tmp1",
                                           Util.getJCRefType(NODE_ITERATOR_SIG),
                                           il.getEnd(), null);
        il.append(new ASTORE(filterTemp.getIndex()));

	_path.translate(classGen, methodGen);
        LocalVariableGen pathTemp =
                methodGen.addLocalVariable("filter_parent_path_tmp2",
                                           Util.getJCRefType(NODE_ITERATOR_SIG),
                                           il.getEnd(), null);
        il.append(new ASTORE(pathTemp.getIndex()));

	il.append(new NEW(cpg.addClass(STEP_ITERATOR_CLASS)));
	il.append(DUP);
        il.append(new ALOAD(filterTemp.getIndex()));
        il.append(new ALOAD(pathTemp.getIndex()));

	// Initialize StepIterator with iterators from the stack
	il.append(new INVOKESPECIAL(initSI));

	// This is a special case for the //* path with or without predicates
        if (_hasDescendantAxis) {
	    final int incl = cpg.addMethodref(NODE_ITERATOR_BASE,
					      "includeSelf",
					      "()" + NODE_ITERATOR_SIG);
	    il.append(new INVOKEVIRTUAL(incl));
	}

	if (!(getParent() instanceof RelativeLocationPath) &&
	    !(getParent() instanceof FilterParentPath)) {
	    final int order = cpg.addInterfaceMethodref(DOM_INTF,
							ORDER_ITERATOR,
							ORDER_ITERATOR_SIG);
	    il.append(methodGen.loadDOM());
	    il.append(SWAP);
	    il.append(methodGen.loadContextNode());
	    il.append(new INVOKEINTERFACE(order, 3));
	}
    
public com.sun.org.apache.xalan.internal.xsltc.compiler.util.TypetypeCheck(com.sun.org.apache.xalan.internal.xsltc.compiler.SymbolTable stable)
Type check a FilterParentPath. If the filter is not a node-set add a cast to node-set only if it is of reference type. This type coercion is needed for expressions like $x/LINE where $x is a parameter reference.

	final Type ftype = _filterExpr.typeCheck(stable);
	if (ftype instanceof NodeSetType == false) {
	    if (ftype instanceof ReferenceType)  {
		_filterExpr = new CastExpr(_filterExpr, Type.NodeSet);
	    }
	    /*
	    else if (ftype instanceof ResultTreeType)  {
		_filterExpr = new CastExpr(_filterExpr, Type.NodeSet);
	    }
	    */
	    else if (ftype instanceof NodeType)  {
		_filterExpr = new CastExpr(_filterExpr, Type.NodeSet);
	    }
	    else {
		throw new TypeCheckError(this);
	    }
	}

	// Wrap single node path in a node set
	final Type ptype = _path.typeCheck(stable);
	if (!(ptype instanceof NodeSetType)) {
	    _path = new CastExpr(_path, Type.NodeSet);
	}

	return _type = Type.NodeSet;