package client.net.sf.saxon.ce.trans; import client.net.sf.saxon.ce.lib.NamespaceConstant; import client.net.sf.saxon.ce.om.StructuredQName; import java.util.HashMap; /** * DecimalFormatManager manages the collection of named and unnamed decimal formats, for use by the * format-number() function. * * <p>In XSLT, there is a single set of decimal formats shared by the whole stylesheet. In XQuery 1.1, however, * each query module has its own set of decimal formats. The DecimalFormatManager to use is therefore linked * from the format-number() call on the expression tree.</p> * @author Michael H. Kay */ public class DecimalFormatManager { private DecimalSymbols defaultDFS; private HashMap<StructuredQName, DecimalFormatInfo> formatTable; // table for named decimal formats private boolean usingOriginalDefault = true; /** * create a DecimalFormatManager and initialise variables */ public DecimalFormatManager() { formatTable = new HashMap(10); defaultDFS = new DecimalSymbols(); } /** * Register the default decimal-format. * Note that it is an error to register the same decimal-format twice, even with different * precedence */ public void setDefaultDecimalFormat(DecimalSymbols dfs, int precedence) throws XPathException { if (!usingOriginalDefault) { if (!dfs.equals(defaultDFS)) { XPathException err = new XPathException("There are two conflicting definitions of the default decimal format"); err.setErrorCode("XTSE1290"); err.setIsStaticError(true); throw err; } } defaultDFS = dfs; usingOriginalDefault = false; setNamedDecimalFormat(DEFAULT_NAME, dfs, precedence); // this is to trigger fixup of calls } final public static StructuredQName DEFAULT_NAME = new StructuredQName("saxon", NamespaceConstant.SAXON, "default-decimal-format"); /** * Method called at the end of stylesheet compilation to fix up any format-number() calls * to the "default default" decimal format */ public void fixupDefaultDefault() throws XPathException { if (usingOriginalDefault) { setNamedDecimalFormat(DEFAULT_NAME, defaultDFS, -1000); } } /** * Get the default decimal-format. */ public DecimalSymbols getDefaultDecimalFormat() { return defaultDFS; } /** * Set a named decimal format. * Note that it is an error to register the same decimal-format twice, unless the values are * equal, or unless there is another of higher precedence. This method assumes that decimal-formats * are registered in order of decreasing precedence * @param qName the name of the decimal format */ public void setNamedDecimalFormat(StructuredQName qName, DecimalSymbols dfs, int precedence) throws XPathException { Object o = formatTable.get(qName); if (o != null) { // if (o instanceof List) { // // this indicates there are forwards references to this decimal format that need to be fixed up // for (Iterator iter = ((List)o).iterator(); iter.hasNext(); ) { // FormatNumber call = (FormatNumber)iter.next(); // call.fixup(dfs); // } // } else { DecimalFormatInfo info = (DecimalFormatInfo)o; DecimalSymbols old = info.dfs; int oldPrecedence = info.precedence; if (precedence < oldPrecedence) { return; } if (precedence==oldPrecedence && !dfs.equals(old)) { XPathException err = new XPathException("There are two conflicting definitions of the named decimal-format"); err.setErrorCode("XTSE1290"); err.setIsStaticError(true); throw err; } // } } DecimalFormatInfo dfi = new DecimalFormatInfo(); dfi.dfs = dfs; dfi.precedence = precedence; formatTable.put(qName, dfi); } /** * Register a format-number() function call that uses a particular decimal format. This * allows early compile time resolution to a DecimalFormatSymbols object where possible, * even in the case of a forwards reference */ // public void registerUsage(StructuredQName qName, FormatNumber call) { // Object o = formatTable.get(qName); // if (o == null) { // // it's a forwards reference // List list = new ArrayList(10); // list.add(call); // formatTable.put(qName, list); // } else if (o instanceof List) { // // it's another forwards reference // List list = (List)o; // list.add(call); // } else { // // it's a backwards reference // DecimalFormatInfo dfi = (DecimalFormatInfo)o; // call.fixup(dfi.dfs); // } // } /** * Get a named decimal-format registered using setNamedDecimalFormat * @param qName The name of the decimal format * @return the DecimalFormatSymbols object corresponding to the named locale, if any * or null if not set. */ public DecimalSymbols getNamedDecimalFormat(StructuredQName qName) { DecimalFormatInfo dfi = ((DecimalFormatInfo)formatTable.get(qName)); if (dfi == null) { return null; } return dfi.dfs; } private static class DecimalFormatInfo { public DecimalSymbols dfs; public int precedence; } } // 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.