001: package net.sf.saxon.trans;
002:
003: import net.sf.saxon.functions.FormatNumber2;
004:
005: import java.io.Serializable;
006: import java.util.ArrayList;
007: import java.util.HashMap;
008: import java.util.Iterator;
009: import java.util.List;
010:
011: /**
012: * DecimalFormatManager manages the collection of named and unnamed decimal formats
013: * @author Michael H. Kay
014: */
015:
016: public class DecimalFormatManager implements Serializable {
017:
018: private DecimalSymbols defaultDFS;
019: private HashMap formatTable; // table for named decimal formats
020: private boolean usingOriginalDefault = true;
021:
022: /**
023: * create a DecimalFormatManager and initialise variables
024: */
025:
026: public DecimalFormatManager() {
027: formatTable = new HashMap(10);
028: DecimalSymbols d = new DecimalSymbols();
029: setDefaults(d);
030: defaultDFS = d;
031: }
032:
033: /**
034: * Set up the XSLT-defined default attributes in a DecimalFormatSymbols
035: */
036:
037: public static void setDefaults(DecimalSymbols d) {
038: d.decimalSeparator = ('.');
039: d.groupingSeparator = (',');
040: d.infinity = ("Infinity");
041: d.minusSign = ('-');
042: d.NaN = ("NaN");
043: d.percent = ('%');
044: d.permill = ('\u2030');
045: d.zeroDigit = ('0');
046: d.digit = ('#');
047: d.patternSeparator = (';');
048: }
049:
050: /**
051: * Register the default decimal-format.
052: * Note that it is an error to register the same decimal-format twice, even with different
053: * precedence
054: */
055:
056: public void setDefaultDecimalFormat(DecimalSymbols dfs,
057: int precedence) throws StaticError {
058: if (!usingOriginalDefault) {
059: if (!dfs.equals(defaultDFS)) {
060: StaticError err = new StaticError(
061: "There are two conflicting definitions of the default decimal format");
062: err.setErrorCode("XTSE1290");
063: throw err;
064: }
065: }
066: defaultDFS = dfs;
067: usingOriginalDefault = false;
068: setNamedDecimalFormat("", "", dfs, precedence);
069: // this is to trigger fixup of calls
070: }
071:
072: /**
073: * Method called at the end of stylesheet compilation to fix up any format-number() calls
074: * to the "default default" decimal format
075: */
076:
077: public void fixupDefaultDefault() throws StaticError {
078: if (usingOriginalDefault) {
079: setNamedDecimalFormat("", "", defaultDFS, -1000);
080: }
081: }
082:
083: /**
084: * Get the default decimal-format.
085: */
086:
087: public DecimalSymbols getDefaultDecimalFormat() {
088: return defaultDFS;
089: }
090:
091: /**
092: * Set a named decimal format.
093: * Note that it is an error to register the same decimal-format twice, unless hte values are
094: * equal, or unless there is another of higher precedence. This method assumes that decimal-formats
095: * are registered in order of decreasing precedence
096: * @param uri The URI of the name of the decimal format
097: * @param localName The local part of the name of the decimal format
098: */
099:
100: public void setNamedDecimalFormat(String uri, String localName,
101: DecimalSymbols dfs, int precedence) throws StaticError {
102: String dfskey = localName + '#' + uri;
103: Object o = formatTable.get(dfskey);
104: if (o != null) {
105: if (o instanceof List) {
106: // this indicates there are forwards references to this decimal format that need to be fixed up
107: for (Iterator iter = ((List) o).iterator(); iter
108: .hasNext();) {
109: FormatNumber2 call = (FormatNumber2) iter.next();
110: call.fixup(dfs);
111: }
112: } else {
113: DecimalFormatInfo info = (DecimalFormatInfo) o;
114: DecimalSymbols old = info.dfs;
115: int oldPrecedence = info.precedence;
116: if (precedence < oldPrecedence) {
117: return;
118: }
119: if (precedence == oldPrecedence && !dfs.equals(old)) {
120: StaticError err = new StaticError(
121: "There are two conflicting definitions of the named decimal-format");
122: err.setErrorCode("XTSE1290");
123: throw err;
124: }
125: }
126: }
127: DecimalFormatInfo dfi = new DecimalFormatInfo();
128: dfi.dfs = dfs;
129: dfi.precedence = precedence;
130: formatTable.put(dfskey, dfi);
131: }
132:
133: /**
134: * Register a format-number() function call that uses a particular decimal format. This
135: * allows early compile time resolution to a DecimalFormatSymbols object where possible,
136: * even in the case of a forwards reference
137: */
138:
139: public void registerUsage(String uri, String localName,
140: FormatNumber2 call) {
141: String dfskey = localName + '#' + uri;
142: Object o = formatTable.get(dfskey);
143: if (o == null) {
144: // it's a forwards reference
145: List list = new ArrayList(10);
146: list.add(call);
147: formatTable.put(dfskey, list);
148: } else if (o instanceof List) {
149: // it's another forwards reference
150: List list = (List) o;
151: list.add(call);
152: } else {
153: // it's a backwards reference
154: DecimalFormatInfo dfi = (DecimalFormatInfo) o;
155: call.fixup(dfi.dfs);
156: }
157: }
158:
159: /**
160: * Get a named decimal-format registered using setNamedDecimalFormat
161: * @param uri The URI of the name of the decimal format
162: * @param localName The local part of the name of the decimal format
163: * @return the DecimalFormatSymbols object corresponding to the named locale, if any
164: * or null if not set.
165: */
166:
167: public DecimalSymbols getNamedDecimalFormat(String uri,
168: String localName) {
169: String dfskey = localName + '#' + uri;
170: DecimalFormatInfo dfi = ((DecimalFormatInfo) formatTable
171: .get(dfskey));
172: if (dfi == null) {
173: return null;
174: }
175: return dfi.dfs;
176: }
177:
178: private static class DecimalFormatInfo implements Serializable {
179: public DecimalSymbols dfs;
180: public int precedence;
181: }
182:
183: }
184:
185: //
186: // The contents of this file are subject to the Mozilla Public License Version 1.0 (the "License");
187: // you may not use this file except in compliance with the License. You may obtain a copy of the
188: // License at http://www.mozilla.org/MPL/
189: //
190: // Software distributed under the License is distributed on an "AS IS" basis,
191: // WITHOUT WARRANTY OF ANY KIND, either express or implied.
192: // See the License for the specific language governing rights and limitations under the License.
193: //
194: // The Original Code is: all this file.
195: //
196: // The Initial Developer of the Original Code is Michael H. Kay.
197: //
198: // Portions created by (your name) are Copyright (C) (your legal entity). All Rights Reserved.
199: //
200: // Contributor(s): none.
201: //
|