
net.sf.saxon.style.XSLSortOrMergeKey Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of Saxon-HE Show documentation
Show all versions of Saxon-HE Show documentation
The XSLT and XQuery Processor
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2015 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.parser.ExpressionTool;
import net.sf.saxon.expr.parser.RoleDiagnostic;
import net.sf.saxon.expr.parser.TypeChecker;
import net.sf.saxon.expr.sort.CodepointCollator;
import net.sf.saxon.expr.sort.SortKeyDefinition;
import net.sf.saxon.lib.NamespaceConstant;
import net.sf.saxon.lib.StringCollator;
import net.sf.saxon.om.AttributeCollection;
import net.sf.saxon.trans.XPathException;
import net.sf.saxon.type.StringConverter;
import net.sf.saxon.type.ValidationFailure;
import net.sf.saxon.value.SequenceType;
import net.sf.saxon.value.StringValue;
import net.sf.saxon.value.Whitespace;
import java.net.URI;
import java.net.URISyntaxException;
public abstract class XSLSortOrMergeKey extends StyleElement {
protected SortKeyDefinition sortKeyDefinition;
protected Expression select;
protected Expression order;
protected Expression dataType = null;
protected Expression caseOrder;
protected Expression lang;
protected Expression collationName;
protected Expression stable;
protected boolean useDefaultCollation = true;
/**
* Determine whether this type of element is allowed to contain a sequence constructor
*
* @return true: yes, it may contain a sequence constructor
*/
public boolean mayContainSequenceConstructor() {
return true;
}
protected String getErrorCode() {
return "XTSE1015";
}
@Override
public void validate(ComponentDeclaration decl) throws XPathException {
if (select != null && hasChildNodes()) {
compileError("An " + getDisplayName() + " element with a select attribute must be empty", getErrorCode());
}
if (select == null && !hasChildNodes()) {
select = new ContextItemExpression();
select.setRetainedStaticContext(getStaticContext().makeRetainedStaticContext());
}
// Get the named or default collation
if (useDefaultCollation) {
collationName = new StringLiteral(getDefaultCollationName());
}
StringCollator stringCollator = null;
if (collationName instanceof StringLiteral) {
String collationString = ((StringLiteral) collationName).getStringValue();
try {
URI collationURI = new URI(collationString);
if (!collationURI.isAbsolute()) {
URI base = new URI(getBaseURI());
collationURI = base.resolve(collationURI);
collationString = collationURI.toString();
}
} catch (URISyntaxException err) {
compileError("Collation name '" + collationString + "' is not a valid URI");
collationString = NamespaceConstant.CODEPOINT_COLLATION_URI;
}
stringCollator = findCollation(collationString, getBaseURI());
if (stringCollator == null) {
compileError("Collation " + collationString + " has not been defined", "XTDE1035");
stringCollator = CodepointCollator.getInstance(); // for recovery paths
}
}
select = typeCheck("select", select);
order = typeCheck("order", order);
caseOrder = typeCheck("case-order", caseOrder);
lang = typeCheck("lang", lang);
dataType = typeCheck("data-type", dataType);
collationName = typeCheck("collation", collationName);
if (select != null) {
try {
RoleDiagnostic role =
new RoleDiagnostic(RoleDiagnostic.INSTRUCTION, getDisplayName() + "//select", 0);
//role.setSourceLocator(new ExpressionLocation(this));
select = TypeChecker.staticTypeCheck(select,
SequenceType.ATOMIC_SEQUENCE,
false, role, makeExpressionVisitor());
} catch (XPathException err) {
compileError(err);
}
}
sortKeyDefinition = new SortKeyDefinition();
sortKeyDefinition.setOrder(order);
sortKeyDefinition.setCaseOrder(caseOrder);
sortKeyDefinition.setLanguage(lang);
sortKeyDefinition.setSortKey(select, true);
sortKeyDefinition.setDataTypeExpression(dataType);
sortKeyDefinition.setCollationNameExpression(collationName);
sortKeyDefinition.setCollation(stringCollator);
sortKeyDefinition.setBaseURI(getBaseURI());
sortKeyDefinition.setStable(stable);
sortKeyDefinition.setBackwardsCompatible(xPath10ModeIsEnabled());
}
protected Expression getStable() {
return stable;
}
@Override
protected void prepareAttributes() throws XPathException {
AttributeCollection atts = getAttributeList();
String selectAtt = null;
String orderAtt = null;
String dataTypeAtt = null;
String caseOrderAtt = null;
String langAtt = null;
String collationAtt = null;
String stableAtt = null;
for (int a = 0; a < atts.getLength(); a++) {
String f = atts.getQName(a);
if (f.equals("select")) {
selectAtt = atts.getValue(a);
select = makeExpression(selectAtt, a);
} else if (f.equals("order")) {
orderAtt = Whitespace.trim(atts.getValue(a));
order = makeAttributeValueTemplate(orderAtt, a);
} else if (f.equals("data-type")) {
dataTypeAtt = Whitespace.trim(atts.getValue(a));
dataType = makeAttributeValueTemplate(dataTypeAtt, a);
} else if (f.equals("case-order")) {
caseOrderAtt = Whitespace.trim(atts.getValue(a));
caseOrder = makeAttributeValueTemplate(caseOrderAtt, a);
} else if (f.equals("lang")) {
langAtt = Whitespace.trim(atts.getValue(a));
lang = makeAttributeValueTemplate(langAtt, a);
} else if (f.equals("collation")) {
collationAtt = Whitespace.trim(atts.getValue(a));
collationName = makeAttributeValueTemplate(collationAtt, a);
} else if (f.equals("stable")) {
stableAtt = Whitespace.trim(atts.getValue(a));
stable = makeAttributeValueTemplate(stableAtt, a);
} else {
checkUnknownAttribute(atts.getNodeName(a));
}
}
if (orderAtt == null) {
order = new StringLiteral("ascending");
} else {
checkAttributeValue("order", orderAtt, true, new String[]{"ascending", "descending"});
}
if (dataTypeAtt == null) {
dataType = null;
}
if (caseOrderAtt == null) {
caseOrder = new StringLiteral("#default");
} else {
checkAttributeValue("case-order", caseOrderAtt, true, new String[]{"lower-first", "upper-first"});
useDefaultCollation = false;
}
if (langAtt == null || langAtt.equals("")) {
lang = new StringLiteral(StringValue.EMPTY_STRING);
} else {
useDefaultCollation = false;
if (lang instanceof StringLiteral) {
String s = ((StringLiteral) lang).getStringValue();
if (s.length() != 0) {
ValidationFailure vf = StringConverter.STRING_TO_LANGUAGE.validate(s);
if (vf != null) {
compileError("The lang attribute must be a valid language code", "XTDE0030");
lang = new StringLiteral(StringValue.EMPTY_STRING);
}
}
}
}
if (stableAtt == null) {
stable = null;
} else {
checkAttributeValue("stable", stableAtt, true, StyleElement.YES_NO);
}
if (collationAtt != null) {
useDefaultCollation = false;
}
}
/*@Nullable*/
public Expression compile(Compilation exec, ComponentDeclaration decl) throws XPathException {
if (select == null) {
Expression b = compileSequenceConstructor(exec, decl, true);
if (b == null) {
b = Literal.makeEmptySequence();
b.setRetainedStaticContext(makeRetainedStaticContext());
}
try {
Expression atomizedSortKey = Atomizer.makeAtomizer(b);
atomizedSortKey = atomizedSortKey.simplify();
ExpressionTool.copyLocationInfo(b, atomizedSortKey);
sortKeyDefinition.setSortKey(atomizedSortKey, true);
select = atomizedSortKey;
} catch (XPathException e) {
compileError(e);
}
}
// Simplify the sort key definition - this is especially important in the case where
// all aspects of the sort key are known statically.
sortKeyDefinition = sortKeyDefinition.simplify();
// not an executable instruction
return null;
}
public SortKeyDefinition getSortKeyDefinition() {
return sortKeyDefinition;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy