Package client.net.sf.saxon.ce.style

Source Code of client.net.sf.saxon.ce.style.XSLForEachGroup

package client.net.sf.saxon.ce.style;
import client.net.sf.saxon.ce.expr.*;
import client.net.sf.saxon.ce.expr.instruct.Executable;
import client.net.sf.saxon.ce.expr.instruct.ForEachGroup;
import client.net.sf.saxon.ce.lib.NamespaceConstant;
import client.net.sf.saxon.ce.lib.StringCollator;
import client.net.sf.saxon.ce.om.AttributeCollection;
import client.net.sf.saxon.ce.om.Axis;
import client.net.sf.saxon.ce.om.StandardNames;
import client.net.sf.saxon.ce.pattern.Pattern;
import client.net.sf.saxon.ce.pattern.PatternSponsor;
import client.net.sf.saxon.ce.trans.XPathException;
import client.net.sf.saxon.ce.tree.util.URI;
import client.net.sf.saxon.ce.value.EmptySequence;
import client.net.sf.saxon.ce.value.SequenceType;
import client.net.sf.saxon.ce.value.Whitespace;


/**
* 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 {

    private Expression select = null;
    private Expression groupBy = null;
    private Expression groupAdjacent = null;
    private Pattern starting = null;
    private Pattern ending = null;
    private Expression collationName;

    /**
    * 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<atts.getLength(); a++) {
      int nc = atts.getNameCode(a);
      String f = getNamePool().getClarkName(nc);
            if (f.equals(StandardNames.SELECT)) {
            selectAtt = atts.getValue(a);
          } else if (f.equals(StandardNames.GROUP_BY)) {
            groupByAtt = atts.getValue(a);
          } else if (f.equals(StandardNames.GROUP_ADJACENT)) {
            groupAdjacentAtt = atts.getValue(a);
          } else if (f.equals(StandardNames.GROUP_STARTING_WITH)) {
            startingAtt = atts.getValue(a);
          } else if (f.equals(StandardNames.GROUP_ENDING_WITH)) {
            endingAtt = atts.getValue(a);
          } else if (f.equals(StandardNames.COLLATION)) {
            collationAtt = Whitespace.trim(atts.getValue(a));
          } else {
            checkUnknownAttribute(nc);
          }
        }

        if (selectAtt==null) {
            reportAbsence("select");
            select = new Literal(EmptySequence.getInstance()); // for error recovery
        } else {
            select = makeExpression(selectAtt);
        }

        int c = (groupByAtt==null ? 0 : 1) +
                (groupAdjacentAtt==null ? 0 : 1) +
                (startingAtt==null ? 0 : 1) +
                (endingAtt==null ? 0 : 1);
        if (c!=1) {
            compileError("Exactly one of the attributes group-by, group-adjacent, group-starting-with, " +
                    "and group-ending-with must be specified", "XTSE1080");
        }

        if (groupByAtt != null) {
            groupBy = makeExpression(groupByAtt);
        }

        if (groupAdjacentAtt != null) {
            groupAdjacent = makeExpression(groupAdjacentAtt);
        }

        if (startingAtt != null) {
            starting = makePattern(startingAtt);
        }

        if (endingAtt != null) {
            ending = makePattern(endingAtt);
        }

        if (collationAtt != null) {
            if (groupBy==null && groupAdjacent==null) {
                compileError("A collation may be specified only if group-by or group-adjacent is specified", "XTSE1090");
            } else {
                collationName = makeAttributeValueTemplate(collationAtt);
                if (collationName instanceof StringLiteral) {
                    String collation = ((StringLiteral)collationName).getStringValue();
                    URI collationURI;
                    try {
                        collationURI = new URI(collation, true);
                        if (!collationURI.isAbsolute()) {
                            URI base = new URI(getBaseURI());
                            collationURI = base.resolve(collationURI.toString());
                            collationName = new StringLiteral(collationURI.toString());
                        }
                    } catch (URI.URISyntaxException err) {
                        compileError("Collation name '" + collationName + "' is not a valid URI", "XTDE1110");
                        collationName = new StringLiteral(NamespaceConstant.CODEPOINT_COLLATION_URI);
                    }
                }
            }
        } else {
            String defaultCollation = getDefaultCollationName();
            if (defaultCollation != null) {
                collationName = new StringLiteral(defaultCollation);
            }
        }
    }

    public void validate(Declaration decl) throws XPathException {
        checkSortComesFirst(false);
        select = typeCheck(select);

        ExpressionVisitor visitor = makeExpressionVisitor();
        if (groupBy != null) {
            groupBy = typeCheck(groupBy);
            try {
                RoleLocator role =
                    new RoleLocator(RoleLocator.INSTRUCTION, "xsl:for-each-group/group-by", 0);
                //role.setSourceLocator(locator);
                groupBy = TypeChecker.staticTypeCheck(groupBy,
                        SequenceType.ATOMIC_SEQUENCE,
                        false, role, visitor);
            } catch (XPathException err) {
                compileError(err);
            }
        } else if (groupAdjacent != null) {
            groupAdjacent = typeCheck(groupAdjacent);
            try {
                RoleLocator role =
                    new RoleLocator(RoleLocator.INSTRUCTION, "xsl:for-each-group/group-adjacent", 0);
                //role.setSourceLocator(locator);
                role.setErrorCode("XTTE1100");
                groupAdjacent = TypeChecker.staticTypeCheck(groupAdjacent,
                        SequenceType.SINGLE_ATOMIC,
                        false, role, visitor);
            } catch (XPathException err) {
                compileError(err);
            }
        }

        starting = typeCheck("starting", starting);
        ending = typeCheck("ending", ending);

        if (starting != null || ending != null) {
            try {
                RoleLocator role =
                    new RoleLocator(RoleLocator.INSTRUCTION, "xsl:for-each-group/select", 0);
                //role.setSourceLocator(locator);
                role.setErrorCode("XTTE1120");
                select = TypeChecker.staticTypeCheck(select,
                                            SequenceType.NODE_SEQUENCE,
                                            false, role, visitor);
            } catch (XPathException err) {
                String prefix = (starting != null ?
                        "With group-starting-with attribute: " :
                        "With group-ending-with attribute: ");
                compileError(prefix + err.getMessage(), err.getErrorCodeQName());
            }
        }
    }

    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 = getConfiguration().getNamedCollation(uri);
            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);
        }

//        Block action = new Block();
//        compileChildren(exec, action, true);
        Expression action = compileSequenceConstructor(exec, decl, iterateAxis(Axis.CHILD));
        if (action == null) {
            // body of for-each is empty: it's a no-op.
            return new Literal(EmptySequence.getInstance());
        }
        try {
            return new ForEachGroup(    select,
                                        makeExpressionVisitor().simplify(action),
                                        algorithm,
                                        key,
                                        collator,
                                        collationName,
                                        getBaseURI(),
                                        makeSortKeys(decl) );
        } catch (XPathException e) {
            compileError(e);
            return null;
        }

    }

}

// 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.
TOP

Related Classes of client.net.sf.saxon.ce.style.XSLForEachGroup

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.