001/*
002 * Units of Measurement Reference Implementation
003 * Copyright (c) 2005-2017, Jean-Marie Dautelle, Werner Keil, V2COM.
004 *
005 * All rights reserved.
006 *
007 * Redistribution and use in source and binary forms, with or without modification,
008 * are permitted provided that the following conditions are met:
009 *
010 * 1. Redistributions of source code must retain the above copyright notice,
011 *    this list of conditions and the following disclaimer.
012 *
013 * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions
014 *    and the following disclaimer in the documentation and/or other materials provided with the distribution.
015 *
016 * 3. Neither the name of JSR-363 nor the names of its contributors may be used to endorse or promote products
017 *    derived from this software without specific prior written permission.
018 *
019 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
020 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
021 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
022 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
023 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
024 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
025 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
026 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
027 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
028 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
029 */
030package tec.units.ri.internal.format.l10n;
031
032/*
033 * Portions Copyright 1999-2010 Research In Motion Limited. 
034 *  295 Phillip Street, Waterloo, Ontario, Canada, N2L 3W8. All Rights Reserved.
035 */
036
037/*
038 * 
039 * Portions Copyright  2000-2006 Sun Microsystems, Inc. All Rights
040 * Reserved.  Use is subject to license terms.
041 */
042
043/*
044 * (C) Copyright Taligent, Inc. 1996, 1997 - All Rights Reserved
045 * (C) Copyright IBM Corp. 1996 - 1998 - All Rights Reserved
046 *
047 *   The original version of this source code and documentation is copyrighted
048 * and owned by Taligent, Inc., a wholly-owned subsidiary of IBM. These
049 * materials are provided under terms of a License Agreement between Taligent
050 * and Sun. This technology is protected by multiple US and International
051 * patents. This notice and attribution to Taligent may not be removed.
052 *   Taligent is a registered trademark of Taligent, Inc.
053 *
054 */
055
056/**
057 * <code>Format</code> is an abstract base class for formatting locale-sensitive information such as dates, messages, and numbers.
058 *
059 * <p>
060 * <code>Format</code> defines the programming interface for formatting locale-sensitive objects into <code>String</code>s (the <code>format</code>
061 * method) and for parsing <code>String</code>s back into objects (the <code>parseObject</code> method).
062 *
063 * <p>
064 * Generally, a format's <code>parseObject</code> method must be able to parse any string formatted by its <code>format</code> method. However, there
065 * may be exceptional cases where this is not possible. For example, a <code>format</code> method might create two adjacent integer numbers with no
066 * separator in between, and in this case the <code>parseObject</code> could not tell which digits belong to which number.
067 *
068 * <h4>Subclassing</h4>
069 *
070 * <p>
071 * The Java 2 platform provides three specialized subclasses of <code>Format</code>-- <code>DateFormat</code>, <code>MessageFormat</code>, and
072 * <code>NumberFormat</code>--for formatting dates, messages, and numbers, respectively.
073 * <p>
074 * Concrete subclasses must implement three methods:
075 * <ol>
076 * <li>
077 * <code>format(Object obj, StringBuffer toAppendTo, FieldPosition pos)</code>
078 * <li> <code>formatToCharacterIterator(Object obj)</code>
079 * <li> <code>parseObject(String source, ParsePosition pos)</code>
080 * </ol>
081 * These general methods allow polymorphic parsing and formatting of objects and are used, for example, by <code>MessageFormat</code>. Subclasses
082 * often also provide additional <code>format</code> methods for specific input types as well as <code>parse</code> methods for specific result types.
083 * Any <code>parse</code> method that does not take a <code>ParsePosition</code> argument should throw <code>ParseException</code> when no text in the
084 * required format is at the beginning of the input text.
085 *
086 * <p>
087 * Most subclasses will also implement the following factory methods:
088 * <ol>
089 * <li>
090 * <code>getInstance</code> for getting a useful format object appropriate for the current locale
091 * <li>
092 * <code>getInstance(Locale)</code> for getting a useful format object appropriate for the specified locale
093 * </ol>
094 * In addition, some subclasses may also implement other <code>getXxxxInstance</code> methods for more specialized control. For example, the
095 * <code>NumberFormat</code> class provides <code>getPercentInstance</code> and <code>getCurrencyInstance</code> methods for getting specialized
096 * number formatters.
097 *
098 * <p>
099 * Subclasses of <code>Format</code> that allow programmers to create objects for locales (with <code>getInstance(Locale)</code> for example) must
100 * also implement the following class method: <blockquote>
101 * 
102 * <pre>
103 * public static Locale[] getAvailableLocales()
104 * </pre>
105 * 
106 * </blockquote>
107 *
108 * <p>
109 * And finally subclasses may define a set of constants to identify the various fields in the formatted output. These constants are used to create a
110 * FieldPosition object which identifies what information is contained in the field and its position in the formatted result. These constants should
111 * be named <code><em>item</em>_FIELD</code> where <code><em>item</em></code> identifies the field.
112 *
113 * <h4><a name="synchronization">Synchronization</a></h4>
114 *
115 * <p>
116 * Formats are generally not synchronized. It is recommended to create separate format instances for each thread. If multiple threads access a format
117 * concurrently, it must be synchronized externally.
118 *
119 * @see ParsePosition
120 * @see FieldPosition
121 * @see NumberFormat
122 * @author Mark Davis
123 */
124public abstract class Format {
125
126  // private static final long serialVersionUID = -299282585814624189L;
127
128  /**
129   * Formats an object to produce a string. This is equivalent to <blockquote> {@link #format(Object, StringBuffer, FieldPosition) format}<code>(obj,
130   *         new StringBuffer(), new FieldPosition(0)).toString();</code> </blockquote>
131   *
132   * @param obj
133   *          The object to format
134   * @return Formatted string.
135   * @exception IllegalArgumentException
136   *              if the Format cannot format the given object
137   */
138  public final String format(Object obj) {
139    return format(obj, new StringBuffer(), new FieldPosition(0)).toString();
140  }
141
142  /**
143   * Formats an object and appends the resulting text to a given string buffer. If the <code>pos</code> argument identifies a field used by the
144   * format, then its indices are set to the beginning and end of the first such field encountered.
145   *
146   * @param obj
147   *          The object to format
148   * @param toAppendTo
149   *          where the text is to be appended
150   * @param pos
151   *          A <code>FieldPosition</code> identifying a field in the formatted text
152   * @return the string buffer passed in as <code>toAppendTo</code>, with formatted text appended
153   * @exception NullPointerException
154   *              if <code>toAppendTo</code> or <code>pos</code> is null
155   * @exception IllegalArgumentException
156   *              if the Format cannot format the given object
157   */
158  public abstract StringBuffer format(Object obj, StringBuffer toAppendTo, FieldPosition pos);
159
160  /**
161   * Formats an Object producing an <code>AttributedCharacterIterator</code>. You can use the returned <code>AttributedCharacterIterator</code> to
162   * build the resulting String, as well as to determine information about the resulting String.
163   * <p>
164   * Each attribute key of the AttributedCharacterIterator will be of type <code>Field</code>. It is up to each <code>Format</code> implementation to
165   * define what the legal values are for each attribute in the <code>AttributedCharacterIterator</code>, but typically the attribute key is also used
166   * as the attribute value.
167   * <p>
168   * The default implementation creates an <code>AttributedCharacterIterator</code> with no attributes. Subclasses that support fields should override
169   * this and create an <code>AttributedCharacterIterator</code> with meaningful attributes.
170   *
171   * @exception NullPointerException
172   *              if obj is null.
173   * @exception IllegalArgumentException
174   *              when the Format cannot format the given object.
175   * @param obj
176   *          The object to format
177   * @return AttributedCharacterIterator describing the formatted value.
178   */
179  AttributedCharacterIterator formatToCharacterIterator(Object obj) {
180    return createAttributedCharacterIterator(format(obj));
181  }
182
183  /**
184   * Parses text from a string to produce an object.
185   * <p>
186   * The method attempts to parse text starting at the index given by <code>pos</code>. If parsing succeeds, then the index of <code>pos</code> is
187   * updated to the index after the last character used (parsing does not necessarily use all characters up to the end of the string), and the parsed
188   * object is returned. The updated <code>pos</code> can be used to indicate the starting point for the next call to this method. If an error occurs,
189   * then the index of <code>pos</code> is not changed, the error index of <code>pos</code> is set to the index of the character where the error
190   * occurred, and null is returned.
191   *
192   * @param source
193   *          A <code>String</code>, part of which should be parsed.
194   * @param pos
195   *          A <code>ParsePosition</code> object with index and error index information as described above.
196   * @return An <code>Object</code> parsed from the string. In case of error, returns null.
197   * @exception NullPointerException
198   *              if <code>pos</code> is null.
199   */
200  // public abstract Object parseObject(String source, ParsePosition pos);
201
202  /**
203   * Parses text from the beginning of the given string to produce an object. The method may not use the entire text of the given string.
204   *
205   * @param source
206   *          A <code>String</code> whose beginning should be parsed.
207   * @return An <code>Object</code> parsed from the string.
208   * @exception ParseException
209   *              if the beginning of the specified string cannot be parsed.
210   */
211  // public Object parseObject(String source) throws ParseException {
212  // ParsePosition pos = new ParsePosition(0);
213  // Object result = parseObject(source, pos);
214  // if (pos.index == 0) {
215  // throw new ParseException(
216  // "Format.parseObject(String) failed", pos.errorIndex);
217  // }
218  // return result;
219  // }
220
221  //
222  // Convenience methods for creating AttributedCharacterIterators from
223  // different parameters.
224  //
225
226  /**
227   * Creates an <code>AttributedCharacterIterator</code> for the String <code>s</code>.
228   *
229   * @param s
230   *          String to create AttributedCharacterIterator from
231   * @return AttributedCharacterIterator wrapping s
232   */
233  AttributedCharacterIterator createAttributedCharacterIterator(String s) {
234    AttributedString as = new AttributedString(s);
235
236    return as.getIterator();
237  }
238
239  /**
240   * Creates an <code>AttributedCharacterIterator</code> containg the concatenated contents of the passed in <code>AttributedCharacterIterator</code>
241   * s.
242   *
243   * @param iterators
244   *          AttributedCharacterIterators used to create resulting AttributedCharacterIterators
245   * @return AttributedCharacterIterator wrapping passed in AttributedCharacterIterators
246   */
247  /*AttributedCharacterIterator createAttributedCharacterIterator(AttributedCharacterIterator[] iterators) {
248    AttributedString as = new AttributedString(iterators);
249
250    return as.getIterator();
251  }*/
252
253  /**
254   * Returns an AttributedCharacterIterator with the String <code>string</code> and additional key/value pair <code>key</code>, <code>value</code>.
255   *
256   * @param string
257   *          String to create AttributedCharacterIterator from
258   * @param key
259   *          Key for AttributedCharacterIterator
260   * @param value
261   *          Value associated with key in AttributedCharacterIterator
262   * @return AttributedCharacterIterator wrapping args
263   */
264  /*AttributedCharacterIterator createAttributedCharacterIterator(String string, Attribute key, Object value) {
265    AttributedString as = new AttributedString(string);
266
267    as.addAttribute(key, value);
268    return as.getIterator();
269  }*/
270
271  /**
272   * Creates an AttributedCharacterIterator with the contents of <code>iterator</code> and the additional attribute <code>key</code>
273   * <code>value</code>.
274   *
275   * @param iterator
276   *          Initial AttributedCharacterIterator to add arg to
277   * @param key
278   *          Key for AttributedCharacterIterator
279   * @param value
280   *          Value associated with key in AttributedCharacterIterator
281   * @return AttributedCharacterIterator wrapping args
282   */
283  /*AttributedCharacterIterator createAttributedCharacterIterator(AttributedCharacterIterator iterator, Attribute key, Object value) {
284    AttributedString as = new AttributedString(iterator);
285
286    as.addAttribute(key, value);
287    return as.getIterator();
288  }*/
289
290  /**
291   * Defines constants that are used as attribute keys in the <code>AttributedCharacterIterator</code> returned from
292   * <code>Format.formatToCharacterIterator</code> and as field identifiers in <code>FieldPosition</code>.
293   *
294   * @since 1.4
295   */
296  public static class Field extends Attribute {
297    /**
298     * Creates a Field with the specified name.
299     *
300     * @param name
301     *          Name of the attribute
302     */
303    protected Field(String name) {
304      super(name);
305    }
306  }
307
308  /**
309   * FieldDelegate is notified by the various <code>Format</code> implementations as they are formatting the Objects. This allows for storage of the
310   * individual sections of the formatted String for later use, such as in a <code>FieldPosition</code> or for an
311   * <code>AttributedCharacterIterator</code>.
312   * <p>
313   * Delegates should NOT assume that the <code>Format</code> will notify the delegate of fields in any particular order.
314   *
315   * @see FieldPosition.Delegate
316   * @see AttributedCharacterFieldDelegate
317   */
318  interface FieldDelegate {
319    /**
320     * Notified when a particular region of the String is formatted. This method will be invoked if there is no corresponding integer field id
321     * matching <code>attr</code>.
322     *
323     * @param attr
324     *          Identifies the field matched
325     * @param value
326     *          Value associated with the field
327     * @param start
328     *          Beginning location of the field, will be >= 0
329     * @param end
330     *          End of the field, will be >= start and <= buffer.length()
331     * @param buffer
332     *          Contains current formatted value, receiver should NOT modify it.
333     */
334    public void formatted(Format.Field attr, Object value, int start, int end, StringBuffer buffer);
335
336    /**
337     * Notified when a particular region of the String is formatted.
338     *
339     * @param fieldID
340     *          Identifies the field by integer
341     * @param attr
342     *          Identifies the field matched
343     * @param value
344     *          Value associated with the field
345     * @param start
346     *          Beginning location of the field, will be >= 0
347     * @param end
348     *          End of the field, will be >= start and <= buffer.length()
349     * @param buffer
350     *          Contains current formatted value, receiver should NOT modify it.
351     */
352    public void formatted(int fieldID, Format.Field attr, Object value, int start, int end, StringBuffer buffer);
353  }
354}