package client.net.sf.saxon.ce.style;
import client.net.sf.saxon.ce.expr.Expression;
import client.net.sf.saxon.ce.expr.instruct.Executable;
import client.net.sf.saxon.ce.om.AttributeCollection;
import client.net.sf.saxon.ce.om.NamespaceException;
import client.net.sf.saxon.ce.om.StandardNames;
import client.net.sf.saxon.ce.om.StructuredQName;
import client.net.sf.saxon.ce.trans.DecimalFormatManager;
import client.net.sf.saxon.ce.trans.DecimalSymbols;
import client.net.sf.saxon.ce.trans.XPathException;
import client.net.sf.saxon.ce.value.StringValue;
import client.net.sf.saxon.ce.value.Whitespace;
/**
* Handler for xsl:decimal-format elements in stylesheet. <br>
*/
public class XSLDecimalFormat extends StyleElement {
boolean prepared = false;
String name;
String decimalSeparator;
String groupingSeparator;
String infinity;
String minusSign;
String NaN;
String percent;
String perMille;
String zeroDigit;
String digit;
String patternSeparator;
/**
* Ask whether this node is a declaration, that is, a permitted child of xsl:stylesheet
* (including xsl:include and xsl:import).
* @return true for this element
*/
@Override
public boolean isDeclaration() {
return true;
}
public void prepareAttributes() throws XPathException {
if (prepared) {
return;
}
prepared = true;
AttributeCollection atts = getAttributeList();
for (int a=0; a<atts.getLength(); a++) {
int nc = atts.getNameCode(a);
String f = getNamePool().getClarkName(nc);
if (f.equals(StandardNames.NAME)) {
name = Whitespace.trim(atts.getValue(a));
} else if (f.equals(StandardNames.DECIMAL_SEPARATOR)) {
decimalSeparator = atts.getValue(a);
} else if (f.equals(StandardNames.GROUPING_SEPARATOR)) {
groupingSeparator = atts.getValue(a);
} else if (f.equals(StandardNames.INFINITY)) {
infinity = atts.getValue(a);
} else if (f.equals(StandardNames.MINUS_SIGN)) {
minusSign = atts.getValue(a);
} else if (f.equals(StandardNames.NAN)) {
NaN = atts.getValue(a);
} else if (f.equals(StandardNames.PERCENT)) {
percent = atts.getValue(a);
} else if (f.equals(StandardNames.PER_MILLE)) {
perMille = atts.getValue(a);
} else if (f.equals(StandardNames.ZERO_DIGIT)) {
zeroDigit = atts.getValue(a);
} else if (f.equals(StandardNames.DIGIT)) {
digit = atts.getValue(a);
} else if (f.equals(StandardNames.PATTERN_SEPARATOR)) {
patternSeparator = atts.getValue(a);
} else {
checkUnknownAttribute(nc);
}
}
}
public void validate(Declaration decl) throws XPathException {
checkTopLevel(null);
checkEmpty();
}
public DecimalSymbols makeDecimalFormatSymbols() throws XPathException {
DecimalSymbols d = new DecimalSymbols();
if (decimalSeparator!=null) {
d.decimalSeparator = (toChar(decimalSeparator));
}
if (groupingSeparator!=null) {
d.groupingSeparator = (toChar(groupingSeparator));
}
if (infinity!=null) {
d.infinity = (infinity);
}
if (minusSign!=null) {
d.minusSign = (toChar(minusSign));
}
if (NaN!=null) {
d.NaN = (NaN);
}
if (percent!=null) {
d.percent = (toChar(percent));
}
if (perMille!=null) {
d.permill = (toChar(perMille));
}
if (zeroDigit!=null) {
d.zeroDigit = (toChar(zeroDigit));
if (!(d.isValidZeroDigit())) {
compileError(
"The value of the zero-digit attribute must be a Unicode digit with value zero",
"XTSE1295");
}
}
if (digit!=null) {
d.digit = (toChar(digit));
}
if (patternSeparator!=null) {
d.patternSeparator = (toChar(patternSeparator));
}
try {
d.checkDistinctRoles();
} catch (XPathException err) {
compileError(err.getMessage(), "XTSE1300");
}
return d;
}
/**
* Method supplied by declaration elements to add themselves to a stylesheet-level index
* @param decl the Declaration being indexed. (This corresponds to the StyleElement object
* except in cases where one module is imported several times with different precedence.)
* @param top the outermost XSLStylesheet element
*/
public void index(Declaration decl, PrincipalStylesheetModule top) throws XPathException
{
prepareAttributes();
DecimalSymbols d = makeDecimalFormatSymbols();
DecimalFormatManager dfm = getPreparedStylesheet().getDecimalFormatManager();
if (name==null) {
try {
dfm.setDefaultDecimalFormat(d, decl.getPrecedence());
} catch (XPathException err) {
compileError(err.getMessage(), err.getErrorCodeQName());
}
} else {
try {
StructuredQName formatName = makeQName(name);
try {
dfm.setNamedDecimalFormat(formatName, d, decl.getPrecedence());
} catch (XPathException err) {
compileError(err.getMessage(), err.getErrorCodeQName());
}
} catch (XPathException err) {
compileError("Invalid decimal format name. " + err.getMessage(), "XTSE0020");
} catch (NamespaceException err) {
compileError("Invalid decimal format name. " + err.getMessage(), "XTSE0280");
}
}
}
public Expression compile(Executable exec, Declaration decl) throws XPathException {
return null;
}
/**
* Get the Unicode codepoint corresponding to a String, which must represent a single Unicode character
* @param s the input string, representing a single Unicode character, perhaps as a surrogate pair
* @return
* @throws XPathException
*/
private int toChar(String s) throws XPathException {
int[] e = StringValue.expand(s);
if (e.length!=1)
compileError("Attribute \"" + s + "\" should be a single character", "XTSE0020");
return e[0];
}
}
// 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.