All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.sf.saxon.style.XSLForEachGroup Maven / Gradle / Ivy

There is a newer version: 10.5
Show newest version
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2013 Saxonica Limited.
// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
// If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
// This Source Code Form is "Incompatible With Secondary Licenses", as defined by the Mozilla Public License, v. 2.0.
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

package net.sf.saxon.style;

import net.sf.saxon.expr.*;
import net.sf.saxon.expr.flwor.LocalVariableBinding;
import net.sf.saxon.expr.instruct.Executable;
import net.sf.saxon.expr.instruct.ForEachGroup;
import net.sf.saxon.expr.parser.ExpressionTool;
import net.sf.saxon.expr.parser.ExpressionVisitor;
import net.sf.saxon.expr.parser.RoleLocator;
import net.sf.saxon.expr.parser.TypeChecker;
import net.sf.saxon.expr.sort.SortKeyDefinition;
import net.sf.saxon.lib.NamespaceConstant;
import net.sf.saxon.lib.StringCollator;
import net.sf.saxon.om.*;
import net.sf.saxon.pattern.Pattern;
import net.sf.saxon.pattern.PatternSponsor;
import net.sf.saxon.trans.SaxonErrorCode;
import net.sf.saxon.trans.XPathException;
import net.sf.saxon.tree.iter.AxisIterator;
import net.sf.saxon.value.DecimalValue;
import net.sf.saxon.value.SequenceType;
import net.sf.saxon.value.Whitespace;

import java.net.URI;
import java.net.URISyntaxException;
import java.util.Iterator;

/**
* Handler for xsl:for-each-group elements in stylesheet. This is a new instruction
* defined in XSLT 2.0
*/

public final class XSLForEachGroup extends StyleElement {

    /*@Nullable*/ private Expression select = null;
    private Expression groupBy = null;
    private Expression groupAdjacent = null;
    private Pattern starting = null;
    private Pattern ending = null;
    private Expression collationName;
    private SourceBinding groupSourceBinding = null;
    private SourceBinding keySourceBinding = null;
    private boolean composite = false;

    /**
    * Determine whether this node is an instruction.
    * @return true - it is an instruction
    */

    public boolean isInstruction() {
        return true;
    }

    /**
     * Specify that xsl:sort is a permitted child
     */

    protected boolean isPermittedChild(StyleElement child) {
        return (child instanceof XSLSort);
    }

    /**
    * Determine whether this type of element is allowed to contain a template-body
    * @return true: yes, it may contain a template-body
    */

    public boolean mayContainSequenceConstructor() {
        return true;
    }

    public void prepareAttributes() throws XPathException {

		AttributeCollection atts = getAttributeList();

		String selectAtt = null;
		String groupByAtt = null;
		String groupAdjacentAtt = null;
		String startingAtt = null;
		String endingAtt = null;
        String collationAtt = null;

		for (int a=0; a sub = exp.iterateSubExpressions(); sub.hasNext();) {
                    checkNoDependency(sub.next(), binding);
                }
            }
        }
    }

    public Expression compile(Executable exec, Declaration decl) throws XPathException {

        StringCollator collator = null;
        if (collationName instanceof StringLiteral) {
            // if the collation name is constant, then we've already resolved it against the base URI
            final String uri = ((StringLiteral)collationName).getStringValue();
            collator = getPrincipalStylesheetModule().findCollation(uri, getBaseURI());
            if (collator==null) {
                compileError("The collation name '" + collationName + "' has not been defined", "XTDE1110");
            }
        }

        byte algorithm = 0;
        Expression key = null;
        if (groupBy != null) {
            algorithm = ForEachGroup.GROUP_BY;
            key = groupBy;
        } else if (groupAdjacent != null) {
            algorithm = ForEachGroup.GROUP_ADJACENT;
            key = groupAdjacent;
        } else if (starting != null) {
            algorithm = ForEachGroup.GROUP_STARTING;
            key = new PatternSponsor(starting);
        } else if (ending != null) {
            algorithm = ForEachGroup.GROUP_ENDING;
            key = new PatternSponsor(ending);
        }

        Expression action = compileSequenceConstructor(exec, decl, iterateAxis(AxisInfo.CHILD), true);
        if (action == null) {
            // body of for-each is empty: it's a no-op.
            return Literal.makeEmptySequence();
        }
        try {
            LocalVariableBinding groupBinding = null;
            LocalVariableBinding keyBinding = null;
            if (groupSourceBinding != null) {
                groupBinding = new LocalVariableBinding(groupSourceBinding.getVariableQName(), SequenceType.ANY_SEQUENCE);
                groupSourceBinding.fixupBinding(groupBinding);
            }
            if (keySourceBinding != null) {
                keyBinding = new LocalVariableBinding(keySourceBinding.getVariableQName(), SequenceType.ANY_SEQUENCE);
                keySourceBinding.fixupBinding(keyBinding);
            }
            ForEachGroup instr = new ForEachGroup(    select,
                                        makeExpressionVisitor().simplify(action),
                                        algorithm,
                                        key,
                                        collator,
                                        collationName,
                                        ExpressionTool.getBaseURI(staticContext, action, true),
                                        makeSortKeys(decl) );

            instr.setGroupBinding(groupBinding);
            instr.setKeyBinding(keyBinding);
            instr.setComposite(composite);
            return instr;
        } catch (XPathException e) {
            compileError(e);
            return null;
        }

    }

    public SourceBinding getGroupSourceBinding() {
        return groupSourceBinding;
    }

    public SourceBinding getKeyBinding() {
        return keySourceBinding;
    }

    public StructuredQName getGroupBindingName() {
        return (groupSourceBinding == null ? null : groupSourceBinding.getVariableQName());
    }

    public StructuredQName getKeyBindingName() {
        return (keySourceBinding == null ? null : keySourceBinding.getVariableQName());
    }

}





© 2015 - 2025 Weber Informatics LLC | Privacy Policy