Path: blob/master/src/java.base/share/classes/java/text/Format.java
41152 views
/*1* Copyright (c) 1996, 2019, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425/*26* (C) Copyright Taligent, Inc. 1996, 1997 - All Rights Reserved27* (C) Copyright IBM Corp. 1996 - 1998 - All Rights Reserved28*29* The original version of this source code and documentation is copyrighted30* and owned by Taligent, Inc., a wholly-owned subsidiary of IBM. These31* materials are provided under terms of a License Agreement between Taligent32* and Sun. This technology is protected by multiple US and International33* patents. This notice and attribution to Taligent may not be removed.34* Taligent is a registered trademark of Taligent, Inc.35*36*/3738package java.text;3940import java.io.Serializable;4142/**43* {@code Format} is an abstract base class for formatting locale-sensitive44* information such as dates, messages, and numbers.45*46* <p>47* {@code Format} defines the programming interface for formatting48* locale-sensitive objects into {@code String}s (the49* {@code format} method) and for parsing {@code String}s back50* into objects (the {@code parseObject} method).51*52* <p>53* Generally, a format's {@code parseObject} method must be able to parse54* any string formatted by its {@code format} method. However, there may55* be exceptional cases where this is not possible. For example, a56* {@code format} method might create two adjacent integer numbers with57* no separator in between, and in this case the {@code parseObject} could58* not tell which digits belong to which number.59*60* <h2>Subclassing</h2>61*62* <p>63* The Java Platform provides three specialized subclasses of {@code Format}--64* {@code DateFormat}, {@code MessageFormat}, and65* {@code NumberFormat}--for formatting dates, messages, and numbers,66* respectively.67* <p>68* Concrete subclasses must implement three methods:69* <ol>70* <li> {@code format(Object obj, StringBuffer toAppendTo, FieldPosition pos)}71* <li> {@code formatToCharacterIterator(Object obj)}72* <li> {@code parseObject(String source, ParsePosition pos)}73* </ol>74* These general methods allow polymorphic parsing and formatting of objects75* and are used, for example, by {@code MessageFormat}.76* Subclasses often also provide additional {@code format} methods for77* specific input types as well as {@code parse} methods for specific78* result types. Any {@code parse} method that does not take a79* {@code ParsePosition} argument should throw {@code ParseException}80* when no text in the required format is at the beginning of the input text.81*82* <p>83* Most subclasses will also implement the following factory methods:84* <ol>85* <li>86* {@code getInstance} for getting a useful format object appropriate87* for the current locale88* <li>89* {@code getInstance(Locale)} for getting a useful format90* object appropriate for the specified locale91* </ol>92* In addition, some subclasses may also implement other93* {@code getXxxxInstance} methods for more specialized control. For94* example, the {@code NumberFormat} class provides95* {@code getPercentInstance} and {@code getCurrencyInstance}96* methods for getting specialized number formatters.97*98* <p>99* Subclasses of {@code Format} that allow programmers to create objects100* for locales (with {@code getInstance(Locale)} for example)101* must also implement the following class method:102* <blockquote>103* <pre>104* public static Locale[] getAvailableLocales()105* </pre>106* </blockquote>107*108* <p>109* And finally subclasses may define a set of constants to identify the various110* fields in the formatted output. These constants are used to create a FieldPosition111* object which identifies what information is contained in the field and its112* position in the formatted result. These constants should be named113* <code><em>item</em>_FIELD</code> where <code><em>item</em></code> identifies114* the field. For examples of these constants, see {@code ERA_FIELD} and its115* friends in {@link DateFormat}.116*117* <h3><a id="synchronization">Synchronization</a></h3>118*119* <p>120* Formats are generally not synchronized.121* It is recommended to create separate format instances for each thread.122* If multiple threads access a format concurrently, it must be synchronized123* externally.124*125* @see java.text.ParsePosition126* @see java.text.FieldPosition127* @see java.text.NumberFormat128* @see java.text.DateFormat129* @see java.text.MessageFormat130* @author Mark Davis131* @since 1.1132*/133public abstract class Format implements Serializable, Cloneable {134135@java.io.Serial136private static final long serialVersionUID = -299282585814624189L;137138/**139* Sole constructor. (For invocation by subclass constructors, typically140* implicit.)141*/142protected Format() {143}144145/**146* Formats an object to produce a string. This is equivalent to147* <blockquote>148* {@link #format(Object, StringBuffer, FieldPosition) format}<code>(obj,149* new StringBuffer(), new FieldPosition(0)).toString();</code>150* </blockquote>151*152* @param obj The object to format153* @return Formatted string.154* @throws IllegalArgumentException if the Format cannot format the given155* object156*/157public final String format (Object obj) {158return format(obj, new StringBuffer(), new FieldPosition(0)).toString();159}160161/**162* Formats an object and appends the resulting text to a given string163* buffer.164* If the {@code pos} argument identifies a field used by the format,165* then its indices are set to the beginning and end of the first such166* field encountered.167*168* @param obj The object to format169* @param toAppendTo where the text is to be appended170* @param pos A {@code FieldPosition} identifying a field171* in the formatted text172* @return the string buffer passed in as {@code toAppendTo},173* with formatted text appended174* @throws NullPointerException if {@code toAppendTo} or175* {@code pos} is null176* @throws IllegalArgumentException if the Format cannot format the given177* object178*/179public abstract StringBuffer format(Object obj,180StringBuffer toAppendTo,181FieldPosition pos);182183/**184* Formats an Object producing an {@code AttributedCharacterIterator}.185* You can use the returned {@code AttributedCharacterIterator}186* to build the resulting String, as well as to determine information187* about the resulting String.188* <p>189* Each attribute key of the AttributedCharacterIterator will be of type190* {@code Field}. It is up to each {@code Format} implementation191* to define what the legal values are for each attribute in the192* {@code AttributedCharacterIterator}, but typically the attribute193* key is also used as the attribute value.194* <p>The default implementation creates an195* {@code AttributedCharacterIterator} with no attributes. Subclasses196* that support fields should override this and create an197* {@code AttributedCharacterIterator} with meaningful attributes.198*199* @throws NullPointerException if obj is null.200* @throws IllegalArgumentException when the Format cannot format the201* given object.202* @param obj The object to format203* @return AttributedCharacterIterator describing the formatted value.204* @since 1.4205*/206public AttributedCharacterIterator formatToCharacterIterator(Object obj) {207return createAttributedCharacterIterator(format(obj));208}209210/**211* Parses text from a string to produce an object.212* <p>213* The method attempts to parse text starting at the index given by214* {@code pos}.215* If parsing succeeds, then the index of {@code pos} is updated216* to the index after the last character used (parsing does not necessarily217* use all characters up to the end of the string), and the parsed218* object is returned. The updated {@code pos} can be used to219* indicate the starting point for the next call to this method.220* If an error occurs, then the index of {@code pos} is not221* changed, the error index of {@code pos} is set to the index of222* the character where the error occurred, and null is returned.223*224* @param source A {@code String}, part of which should be parsed.225* @param pos A {@code ParsePosition} object with index and error226* index information as described above.227* @return An {@code Object} parsed from the string. In case of228* error, returns null.229* @throws NullPointerException if {@code source} or {@code pos} is null.230*/231public abstract Object parseObject (String source, ParsePosition pos);232233/**234* Parses text from the beginning of the given string to produce an object.235* The method may not use the entire text of the given string.236*237* @param source A {@code String} whose beginning should be parsed.238* @return An {@code Object} parsed from the string.239* @throws ParseException if the beginning of the specified string240* cannot be parsed.241* @throws NullPointerException if {@code source} is null.242*/243public Object parseObject(String source) throws ParseException {244ParsePosition pos = new ParsePosition(0);245Object result = parseObject(source, pos);246if (pos.index == 0) {247throw new ParseException("Format.parseObject(String) failed",248pos.errorIndex);249}250return result;251}252253/**254* Creates and returns a copy of this object.255*256* @return a clone of this instance.257*/258public Object clone() {259try {260return super.clone();261} catch (CloneNotSupportedException e) {262// will never happen263throw new InternalError(e);264}265}266267//268// Convenience methods for creating AttributedCharacterIterators from269// different parameters.270//271272/**273* Creates an {@code AttributedCharacterIterator} for the String274* {@code s}.275*276* @param s String to create AttributedCharacterIterator from277* @return AttributedCharacterIterator wrapping s278*/279AttributedCharacterIterator createAttributedCharacterIterator(String s) {280AttributedString as = new AttributedString(s);281282return as.getIterator();283}284285/**286* Creates an {@code AttributedCharacterIterator} containing the287* concatenated contents of the passed in288* {@code AttributedCharacterIterator}s.289*290* @param iterators AttributedCharacterIterators used to create resulting291* AttributedCharacterIterators292* @return AttributedCharacterIterator wrapping passed in293* AttributedCharacterIterators294*/295AttributedCharacterIterator createAttributedCharacterIterator(296AttributedCharacterIterator[] iterators) {297AttributedString as = new AttributedString(iterators);298299return as.getIterator();300}301302/**303* Returns an AttributedCharacterIterator with the String304* {@code string} and additional key/value pair {@code key},305* {@code value}.306*307* @param string String to create AttributedCharacterIterator from308* @param key Key for AttributedCharacterIterator309* @param value Value associated with key in AttributedCharacterIterator310* @return AttributedCharacterIterator wrapping args311*/312AttributedCharacterIterator createAttributedCharacterIterator(313String string, AttributedCharacterIterator.Attribute key,314Object value) {315AttributedString as = new AttributedString(string);316317as.addAttribute(key, value);318return as.getIterator();319}320321/**322* Creates an AttributedCharacterIterator with the contents of323* {@code iterator} and the additional attribute {@code key}324* {@code value}.325*326* @param iterator Initial AttributedCharacterIterator to add arg to327* @param key Key for AttributedCharacterIterator328* @param value Value associated with key in AttributedCharacterIterator329* @return AttributedCharacterIterator wrapping args330*/331AttributedCharacterIterator createAttributedCharacterIterator(332AttributedCharacterIterator iterator,333AttributedCharacterIterator.Attribute key, Object value) {334AttributedString as = new AttributedString(iterator);335336as.addAttribute(key, value);337return as.getIterator();338}339340341/**342* Defines constants that are used as attribute keys in the343* {@code AttributedCharacterIterator} returned344* from {@code Format.formatToCharacterIterator} and as345* field identifiers in {@code FieldPosition}.346*347* @since 1.4348*/349public static class Field extends AttributedCharacterIterator.Attribute {350351// Proclaim serial compatibility with 1.4 FCS352@java.io.Serial353private static final long serialVersionUID = 276966692217360283L;354355/**356* Creates a Field with the specified name.357*358* @param name Name of the attribute359*/360protected Field(String name) {361super(name);362}363}364365366/**367* FieldDelegate is notified by the various {@code Format}368* implementations as they are formatting the Objects. This allows for369* storage of the individual sections of the formatted String for370* later use, such as in a {@code FieldPosition} or for an371* {@code AttributedCharacterIterator}.372* <p>373* Delegates should NOT assume that the {@code Format} will notify374* the delegate of fields in any particular order.375*376* @see FieldPosition#getFieldDelegate377* @see CharacterIteratorFieldDelegate378*/379interface FieldDelegate {380/**381* Notified when a particular region of the String is formatted. This382* method will be invoked if there is no corresponding integer field id383* matching {@code attr}.384*385* @param attr Identifies the field matched386* @param value Value associated with the field387* @param start Beginning location of the field, will be >= 0388* @param end End of the field, will be >= start and <= buffer.length()389* @param buffer Contains current formatted value, receiver should390* NOT modify it.391*/392public void formatted(Format.Field attr, Object value, int start,393int end, StringBuffer buffer);394395/**396* Notified when a particular region of the String is formatted.397*398* @param fieldID Identifies the field by integer399* @param attr Identifies the field matched400* @param value Value associated with the field401* @param start Beginning location of the field, will be >= 0402* @param end End of the field, will be >= start and <= buffer.length()403* @param buffer Contains current formatted value, receiver should404* NOT modify it.405*/406public void formatted(int fieldID, Format.Field attr, Object value,407int start, int end, StringBuffer buffer);408}409}410411412