1 /*
2  * Copyright (c) 1996, 2019, Oracle and/or its affiliates. All rights reserved.
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * This code is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 only, as
7  * published by the Free Software Foundation.  Oracle designates this
8  * particular file as subject to the "Classpath" exception as provided
9  * by Oracle in the LICENSE file that accompanied this code.
10  *
11  * This code is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14  * version 2 for more details (a copy is included in the LICENSE file that
15  * accompanied this code).
16  *
17  * You should have received a copy of the GNU General Public License version
18  * 2 along with this work; if not, write to the Free Software Foundation,
19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20  *
21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22  * or visit www.oracle.com if you need additional information or have any
23  * questions.
24  */
25 
26 /*
27  * (C) Copyright Taligent, Inc. 1996, 1997 - All Rights Reserved
28  * (C) Copyright IBM Corp. 1996 - 1998 - All Rights Reserved
29  *
30  *   The original version of this source code and documentation is copyrighted
31  * and owned by Taligent, Inc., a wholly-owned subsidiary of IBM. These
32  * materials are provided under terms of a License Agreement between Taligent
33  * and Sun. This technology is protected by multiple US and International
34  * patents. This notice and attribution to Taligent may not be removed.
35  *   Taligent is a registered trademark of Taligent, Inc.
36  *
37  */
38 
39 package java.text;
40 
41 import java.io.Serializable;
42 
43 /**
44  * {@code Format} is an abstract base class for formatting locale-sensitive
45  * information such as dates, messages, and numbers.
46  *
47  * <p>
48  * {@code Format} defines the programming interface for formatting
49  * locale-sensitive objects into {@code String}s (the
50  * {@code format} method) and for parsing {@code String}s back
51  * into objects (the {@code parseObject} method).
52  *
53  * <p>
54  * Generally, a format's {@code parseObject} method must be able to parse
55  * any string formatted by its {@code format} method. However, there may
56  * be exceptional cases where this is not possible. For example, a
57  * {@code format} method might create two adjacent integer numbers with
58  * no separator in between, and in this case the {@code parseObject} could
59  * not tell which digits belong to which number.
60  *
61  * <h2>Subclassing</h2>
62  *
63  * <p>
64  * The Java Platform provides three specialized subclasses of {@code Format}--
65  * {@code DateFormat}, {@code MessageFormat}, and
66  * {@code NumberFormat}--for formatting dates, messages, and numbers,
67  * respectively.
68  * <p>
69  * Concrete subclasses must implement three methods:
70  * <ol>
71  * <li> {@code format(Object obj, StringBuffer toAppendTo, FieldPosition pos)}
72  * <li> {@code formatToCharacterIterator(Object obj)}
73  * <li> {@code parseObject(String source, ParsePosition pos)}
74  * </ol>
75  * These general methods allow polymorphic parsing and formatting of objects
76  * and are used, for example, by {@code MessageFormat}.
77  * Subclasses often also provide additional {@code format} methods for
78  * specific input types as well as {@code parse} methods for specific
79  * result types. Any {@code parse} method that does not take a
80  * {@code ParsePosition} argument should throw {@code ParseException}
81  * when no text in the required format is at the beginning of the input text.
82  *
83  * <p>
84  * Most subclasses will also implement the following factory methods:
85  * <ol>
86  * <li>
87  * {@code getInstance} for getting a useful format object appropriate
88  * for the current locale
89  * <li>
90  * {@code getInstance(Locale)} for getting a useful format
91  * object appropriate for the specified locale
92  * </ol>
93  * In addition, some subclasses may also implement other
94  * {@code getXxxxInstance} methods for more specialized control. For
95  * example, the {@code NumberFormat} class provides
96  * {@code getPercentInstance} and {@code getCurrencyInstance}
97  * methods for getting specialized number formatters.
98  *
99  * <p>
100  * Subclasses of {@code Format} that allow programmers to create objects
101  * for locales (with {@code getInstance(Locale)} for example)
102  * must also implement the following class method:
103  * <blockquote>
104  * <pre>
105  * public static Locale[] getAvailableLocales()
106  * </pre>
107  * </blockquote>
108  *
109  * <p>
110  * And finally subclasses may define a set of constants to identify the various
111  * fields in the formatted output. These constants are used to create a FieldPosition
112  * object which identifies what information is contained in the field and its
113  * position in the formatted result. These constants should be named
114  * <code><em>item</em>_FIELD</code> where <code><em>item</em></code> identifies
115  * the field. For examples of these constants, see {@code ERA_FIELD} and its
116  * friends in {@link DateFormat}.
117  *
118  * <h3><a id="synchronization">Synchronization</a></h3>
119  *
120  * <p>
121  * Formats are generally not synchronized.
122  * It is recommended to create separate format instances for each thread.
123  * If multiple threads access a format concurrently, it must be synchronized
124  * externally.
125  *
126  * @see          java.text.ParsePosition
127  * @see          java.text.FieldPosition
128  * @see          java.text.NumberFormat
129  * @see          java.text.DateFormat
130  * @see          java.text.MessageFormat
131  * @author       Mark Davis
132  * @since 1.1
133  */
134 public abstract class Format implements Serializable, Cloneable {
135 
136     @java.io.Serial
137     private static final long serialVersionUID = -299282585814624189L;
138 
139     /**
140      * Sole constructor.  (For invocation by subclass constructors, typically
141      * implicit.)
142      */
Format()143     protected Format() {
144     }
145 
146     /**
147      * Formats an object to produce a string. This is equivalent to
148      * <blockquote>
149      * {@link #format(Object, StringBuffer, FieldPosition) format}<code>(obj,
150      *         new StringBuffer(), new FieldPosition(0)).toString();</code>
151      * </blockquote>
152      *
153      * @param obj    The object to format
154      * @return       Formatted string.
155      * @throws    IllegalArgumentException if the Format cannot format the given
156      *            object
157      */
format(Object obj)158     public final String format (Object obj) {
159         return format(obj, new StringBuffer(), new FieldPosition(0)).toString();
160     }
161 
162     /**
163      * Formats an object and appends the resulting text to a given string
164      * buffer.
165      * If the {@code pos} argument identifies a field used by the format,
166      * then its indices are set to the beginning and end of the first such
167      * field encountered.
168      *
169      * @param obj    The object to format
170      * @param toAppendTo    where the text is to be appended
171      * @param pos    A {@code FieldPosition} identifying a field
172      *               in the formatted text
173      * @return       the string buffer passed in as {@code toAppendTo},
174      *               with formatted text appended
175      * @throws    NullPointerException if {@code toAppendTo} or
176      *            {@code pos} is null
177      * @throws    IllegalArgumentException if the Format cannot format the given
178      *            object
179      */
format(Object obj, StringBuffer toAppendTo, FieldPosition pos)180     public abstract StringBuffer format(Object obj,
181                     StringBuffer toAppendTo,
182                     FieldPosition pos);
183 
184     /**
185      * Formats an Object producing an {@code AttributedCharacterIterator}.
186      * You can use the returned {@code AttributedCharacterIterator}
187      * to build the resulting String, as well as to determine information
188      * about the resulting String.
189      * <p>
190      * Each attribute key of the AttributedCharacterIterator will be of type
191      * {@code Field}. It is up to each {@code Format} implementation
192      * to define what the legal values are for each attribute in the
193      * {@code AttributedCharacterIterator}, but typically the attribute
194      * key is also used as the attribute value.
195      * <p>The default implementation creates an
196      * {@code AttributedCharacterIterator} with no attributes. Subclasses
197      * that support fields should override this and create an
198      * {@code AttributedCharacterIterator} with meaningful attributes.
199      *
200      * @throws    NullPointerException if obj is null.
201      * @throws    IllegalArgumentException when the Format cannot format the
202      *            given object.
203      * @param obj The object to format
204      * @return AttributedCharacterIterator describing the formatted value.
205      * @since 1.4
206      */
formatToCharacterIterator(Object obj)207     public AttributedCharacterIterator formatToCharacterIterator(Object obj) {
208         return createAttributedCharacterIterator(format(obj));
209     }
210 
211     /**
212      * Parses text from a string to produce an object.
213      * <p>
214      * The method attempts to parse text starting at the index given by
215      * {@code pos}.
216      * If parsing succeeds, then the index of {@code pos} is updated
217      * to the index after the last character used (parsing does not necessarily
218      * use all characters up to the end of the string), and the parsed
219      * object is returned. The updated {@code pos} can be used to
220      * indicate the starting point for the next call to this method.
221      * If an error occurs, then the index of {@code pos} is not
222      * changed, the error index of {@code pos} is set to the index of
223      * the character where the error occurred, and null is returned.
224      *
225      * @param source A {@code String}, part of which should be parsed.
226      * @param pos A {@code ParsePosition} object with index and error
227      *            index information as described above.
228      * @return An {@code Object} parsed from the string. In case of
229      *         error, returns null.
230      * @throws NullPointerException if {@code source} or {@code pos} is null.
231      */
parseObject(String source, ParsePosition pos)232     public abstract Object parseObject (String source, ParsePosition pos);
233 
234     /**
235      * Parses text from the beginning of the given string to produce an object.
236      * The method may not use the entire text of the given string.
237      *
238      * @param source A {@code String} whose beginning should be parsed.
239      * @return An {@code Object} parsed from the string.
240      * @throws    ParseException if the beginning of the specified string
241      *            cannot be parsed.
242      * @throws NullPointerException if {@code source} is null.
243      */
parseObject(String source)244     public Object parseObject(String source) throws ParseException {
245         ParsePosition pos = new ParsePosition(0);
246         Object result = parseObject(source, pos);
247         if (pos.index == 0) {
248             throw new ParseException("Format.parseObject(String) failed",
249                 pos.errorIndex);
250         }
251         return result;
252     }
253 
254     /**
255      * Creates and returns a copy of this object.
256      *
257      * @return a clone of this instance.
258      */
clone()259     public Object clone() {
260         try {
261             return super.clone();
262         } catch (CloneNotSupportedException e) {
263             // will never happen
264             throw new InternalError(e);
265         }
266     }
267 
268     //
269     // Convenience methods for creating AttributedCharacterIterators from
270     // different parameters.
271     //
272 
273     /**
274      * Creates an {@code AttributedCharacterIterator} for the String
275      * {@code s}.
276      *
277      * @param s String to create AttributedCharacterIterator from
278      * @return AttributedCharacterIterator wrapping s
279      */
createAttributedCharacterIterator(String s)280     AttributedCharacterIterator createAttributedCharacterIterator(String s) {
281         AttributedString as = new AttributedString(s);
282 
283         return as.getIterator();
284     }
285 
286     /**
287      * Creates an {@code AttributedCharacterIterator} containing the
288      * concatenated contents of the passed in
289      * {@code AttributedCharacterIterator}s.
290      *
291      * @param iterators AttributedCharacterIterators used to create resulting
292      *                  AttributedCharacterIterators
293      * @return AttributedCharacterIterator wrapping passed in
294      *         AttributedCharacterIterators
295      */
createAttributedCharacterIterator( AttributedCharacterIterator[] iterators)296     AttributedCharacterIterator createAttributedCharacterIterator(
297                        AttributedCharacterIterator[] iterators) {
298         AttributedString as = new AttributedString(iterators);
299 
300         return as.getIterator();
301     }
302 
303     /**
304      * Returns an AttributedCharacterIterator with the String
305      * {@code string} and additional key/value pair {@code key},
306      * {@code value}.
307      *
308      * @param string String to create AttributedCharacterIterator from
309      * @param key Key for AttributedCharacterIterator
310      * @param value Value associated with key in AttributedCharacterIterator
311      * @return AttributedCharacterIterator wrapping args
312      */
createAttributedCharacterIterator( String string, AttributedCharacterIterator.Attribute key, Object value)313     AttributedCharacterIterator createAttributedCharacterIterator(
314                       String string, AttributedCharacterIterator.Attribute key,
315                       Object value) {
316         AttributedString as = new AttributedString(string);
317 
318         as.addAttribute(key, value);
319         return as.getIterator();
320     }
321 
322     /**
323      * Creates an AttributedCharacterIterator with the contents of
324      * {@code iterator} and the additional attribute {@code key}
325      * {@code value}.
326      *
327      * @param iterator Initial AttributedCharacterIterator to add arg to
328      * @param key Key for AttributedCharacterIterator
329      * @param value Value associated with key in AttributedCharacterIterator
330      * @return AttributedCharacterIterator wrapping args
331      */
createAttributedCharacterIterator( AttributedCharacterIterator iterator, AttributedCharacterIterator.Attribute key, Object value)332     AttributedCharacterIterator createAttributedCharacterIterator(
333               AttributedCharacterIterator iterator,
334               AttributedCharacterIterator.Attribute key, Object value) {
335         AttributedString as = new AttributedString(iterator);
336 
337         as.addAttribute(key, value);
338         return as.getIterator();
339     }
340 
341 
342     /**
343      * Defines constants that are used as attribute keys in the
344      * {@code AttributedCharacterIterator} returned
345      * from {@code Format.formatToCharacterIterator} and as
346      * field identifiers in {@code FieldPosition}.
347      *
348      * @since 1.4
349      */
350     public static class Field extends AttributedCharacterIterator.Attribute {
351 
352         // Proclaim serial compatibility with 1.4 FCS
353         @java.io.Serial
354         private static final long serialVersionUID = 276966692217360283L;
355 
356         /**
357          * Creates a Field with the specified name.
358          *
359          * @param name Name of the attribute
360          */
Field(String name)361         protected Field(String name) {
362             super(name);
363         }
364     }
365 
366 
367     /**
368      * FieldDelegate is notified by the various {@code Format}
369      * implementations as they are formatting the Objects. This allows for
370      * storage of the individual sections of the formatted String for
371      * later use, such as in a {@code FieldPosition} or for an
372      * {@code AttributedCharacterIterator}.
373      * <p>
374      * Delegates should NOT assume that the {@code Format} will notify
375      * the delegate of fields in any particular order.
376      *
377      * @see FieldPosition#getFieldDelegate
378      * @see CharacterIteratorFieldDelegate
379      */
380     interface FieldDelegate {
381         /**
382          * Notified when a particular region of the String is formatted. This
383          * method will be invoked if there is no corresponding integer field id
384          * matching {@code attr}.
385          *
386          * @param attr Identifies the field matched
387          * @param value Value associated with the field
388          * @param start Beginning location of the field, will be >= 0
389          * @param end End of the field, will be >= start and <= buffer.length()
390          * @param buffer Contains current formatted value, receiver should
391          *        NOT modify it.
392          */
formatted(Format.Field attr, Object value, int start, int end, StringBuffer buffer)393         public void formatted(Format.Field attr, Object value, int start,
394                               int end, StringBuffer buffer);
395 
396         /**
397          * Notified when a particular region of the String is formatted.
398          *
399          * @param fieldID Identifies the field by integer
400          * @param attr Identifies the field matched
401          * @param value Value associated with the field
402          * @param start Beginning location of the field, will be >= 0
403          * @param end End of the field, will be >= start and <= buffer.length()
404          * @param buffer Contains current formatted value, receiver should
405          *        NOT modify it.
406          */
formatted(int fieldID, Format.Field attr, Object value, int start, int end, StringBuffer buffer)407         public void formatted(int fieldID, Format.Field attr, Object value,
408                               int start, int end, StringBuffer buffer);
409     }
410 }
411