All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.time4j.format.Attributes Maven / Gradle / Ivy

/*
 * -----------------------------------------------------------------------
 * Copyright © 2013-2014 Meno Hochschild, 
 * -----------------------------------------------------------------------
 * This file (Attributes.java) is part of project Time4J.
 *
 * Time4J is free software: You can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as published
 * by the Free Software Foundation, either version 2.1 of the License, or
 * (at your option) any later version.
 *
 * Time4J is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with Time4J. If not, see .
 * -----------------------------------------------------------------------
 */

package net.time4j.format;

import net.time4j.engine.AttributeKey;
import net.time4j.engine.AttributeQuery;
import net.time4j.engine.ChronoCondition;
import net.time4j.engine.ChronoDisplay;
import net.time4j.tz.TZID;
import net.time4j.tz.Timezone;
import net.time4j.tz.TransitionStrategy;

import java.util.Collections;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.ServiceLoader;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

import static net.time4j.format.Leniency.LAX;
import static net.time4j.format.Leniency.SMART;
import static net.time4j.format.Leniency.STRICT;


/**
 * 

A collection of format attributes for controlling the formatting * and parsing.

* * @author Meno Hochschild * @concurrency */ /*[deutsch] *

Formatattribute zum Steuern des Format- und Interpretierungsvorgangs.

* * @author Meno Hochschild * @concurrency */ public final class Attributes implements AttributeQuery { //~ Statische Felder/Initialisierungen -------------------------------- private static final NumberSymbolProvider NUMBER_SYMBOLS; static { NumberSymbolProvider p = null; ClassLoader cl = Thread.currentThread().getContextClassLoader(); if (cl == null) { cl = NumberSymbolProvider.class.getClassLoader(); } for ( NumberSymbolProvider tmp : ServiceLoader.load(NumberSymbolProvider.class, cl) ) { p = tmp; break; } if (p == null) { p = NumberSymbolProvider.DEFAULT; } NUMBER_SYMBOLS = p; } /** *

Attribute for the calendar type.

* *

Default value: {@link CalendarText#ISO_CALENDAR_TYPE}

*/ /*[deutsch] *

Gibt den Kalendertyp an.

* *

Standardwert: {@link CalendarText#ISO_CALENDAR_TYPE}

*/ public static final AttributeKey CALENDAR_TYPE = PredefinedKey.valueOf("CALENDAR_TYPE", String.class); /** *

Attribute controlling the language output and parsing of * chronological texts (for example month names).

* *

Default value: {@code Locale.ROOT}.

*/ /*[deutsch] *

Gibt die Sprach- und Ländereinstellung an, die die * Sprachausgabe von chronologischen Texten (Beispiel Monatsnamen) * steuert.

* *

Standardwert: {@code Locale.ROOT}.

*/ public static final AttributeKey LANGUAGE = PredefinedKey.valueOf("LANGUAGE", Locale.class); /** *

Attribute denoting the timezone identifier for display purposes.

* *

When printing a global type this attribute controls the zonal * representation. If this attribute is missing then Time4J will throw * an exception because the internal timezone reference UTC+00:00 of * global types is not intended to be used for display purposes.

* *

When parsing a global type this attribute serves as replacement * timezone if the parsing has not recognized any timezone or offset * information in the text to be parsed. If the attribute is also missing * then Time4J will throw an exception.

* *

Note that before version v2.0 the behaviour of Time4J was * different. When printing, the default {@code ZonalOffset.UTC} was used. * When parsing, the system default timezone was used as default in case * of missing attribute and lax mode.

* * @see ChronoFormatter#withTimezone(TZID) */ /*[deutsch] *

Gibt die Zeitzonen-ID für die Verwendung in formatierten * Darstellungen an.

* *

In der Textausgabe von globalen Typen kontrolliert dieses Attribut * die zonale Darstellung. Fehlt das Attribut, wird Time4J eine Ausnahme * werfen, weil der interne Zeitzonenbezug UTC+00:00 von globalen Typen * nicht für Anzeigezwecke gedacht ist.

* *

Wenn umgekehrt ein Text als globaler Typ interpretiert werden soll, * dient dieses Attribut als Ersatzwert, falls beim Parsen im Text keine * Zeitzone und auch kein Offset erkannt werden konnten. Fehlt auch hier * das Attribut, wird eine Ausnahme geworfen.

* *

Hinweis: Vor Version v2.0 war das Verhalten von Time4J anders. * In der Textausgabe war der Standard immer {@code ZonalOffset.UTC}. * Beim Parsen war die Systemzeitzone die Vorgabe im laxen Modus * gewesen, bevor eine Ausnahme flog.

* * @see ChronoFormatter#withTimezone(TZID) */ public static final AttributeKey TIMEZONE_ID = PredefinedKey.valueOf("TIMEZONE_ID", TZID.class); /** *

Attribute for the conflict strategy to be used in resolving * ambivalent or invalid local timestamps.

* *

If this attribute is missing then Time4J will assume the default * conflict strategy.

* * @see net.time4j.tz.Timezone#DEFAULT_CONFLICT_STRATEGY */ /*[deutsch] *

Gibt die Konfliktstrategie an, die bei der Auflösung von nicht * eindeutigen lokalen Zeitstempeln zu verwenden ist.

* *

Fehlt das Attribut, wird eine Standardstrategie angenommen.

* * @see net.time4j.tz.Timezone#DEFAULT_CONFLICT_STRATEGY */ public static final AttributeKey TRANSITION_STRATEGY = PredefinedKey.valueOf("TRANSITION_STRATEGY", TransitionStrategy.class); /** *

Attribute which controls the leniency in parsing.

* *

Setting of this attribute also changes other attributes:

* * * * * * * * * * *
LENIENCYPARSE_CASE_INSENSITIVEPARSE_PARTIAL_COMPARETRAILING_CHARACTERS
STRICTfalsefalsefalse
SMARTtruefalsefalse
LAXtruetruetrue
* *

Default value: {@link Leniency#SMART}

*/ /*[deutsch] *

Legt den Nachsichtigkeitsmodus beim Parsen fest.

* *

Das Setzen dieses Attributs beeinflußt auch andere * Attribute:

* * * * * * * * * * *
LENIENCYPARSE_CASE_INSENSITIVEPARSE_PARTIAL_COMPARETRAILING_CHARACTERS
STRICTfalsefalsefalse
SMARTtruefalsefalse
LAXtruetruetrue
* *

Standardwert: {@link Leniency#SMART}

*/ public static final AttributeKey LENIENCY = PredefinedKey.valueOf("LENIENCY", Leniency.class); /** *

Determines the text width to be used in formatting and parsing.

* *

Default value: {@link TextWidth#WIDE}

*/ /*[deutsch] *

Gibt die verwendete Textbreite an.

* *

Standardwert: {@link TextWidth#WIDE}

*/ public static final AttributeKey TEXT_WIDTH = PredefinedKey.valueOf("TEXT_WIDTH", TextWidth.class); /** *

Determines the output context to be used in formatting and * parsing.

* *

Default value: {@link OutputContext#FORMAT}

*/ /*[deutsch] *

Gibt den verwendeten Ausgabekontext an.

* *

Standardwert: {@link OutputContext#FORMAT}

*/ public static final AttributeKey OUTPUT_CONTEXT = PredefinedKey.valueOf("OUTPUT_CONTEXT", OutputContext.class); /** *

This attribute controls if the case of text is irrelevant * in parsing or not.

* *

Default value: {@code true}

*/ /*[deutsch] *

Steuert, ob beim Parsen die Groß- und Kleinschreibung * außer Acht gelassen werden soll.

* *

Standardwert: {@code true}

*/ public static final AttributeKey PARSE_CASE_INSENSITIVE = PredefinedKey.valueOf("PARSE_CASE_INSENSITIVE", Boolean.class); /** *

This attribute controls if the parser will only check the * start of a chronological text.

* *

Abbreviations can be parsed by help of this attribute, too. * Default value: {@code false}

*/ /*[deutsch] *

Steuert, ob beim Parsen nur Textanfänge geprüft werden * sollen.

* *

Mit diesem Attribut können auch Abkürzungen noch * sinnvoll interpretiert werden. Standardwert: {@code false}

*/ public static final AttributeKey PARSE_PARTIAL_COMPARE = PredefinedKey.valueOf("PARSE_PARTIAL_COMPARE", Boolean.class); /** *

Determines the unicode char for the zero digit..

* *

In case of changing the language setting this attribute will * automatically be adjusted. Default value is the arab digit * {@code 0} in ISO-8601 (corresponding to the ASCII-value 48).

*/ /*[deutsch] *

Legt das Unicode-Zeichen für die Null-Ziffer fest.

* *

Diese Einstellung wird bei jeder Änderung der Spracheinstellung * automatisch angepasst. Standardwert ist in ISO-8601 die arabische Ziffer * {@code 0} (entsprechend dem ASCII-Wert 48).

*/ public static final AttributeKey ZERO_DIGIT = PredefinedKey.valueOf("ZERO_DIGIT", Character.class); /** *

Determines the unicode char for the decimal separator.

* *

In case of changing the language setting this attribute will * automatically be adjusted. Default value is the comma in ISO-8601 * corresponding to the ASCII-value 44. With help of the boolean * system property "net.time4j.format.iso.decimal.dot", * the dot can be defined as alternative default value.

*/ /*[deutsch] *

Legt das Unicode-Zeichen für das Dezimaltrennzeichen fest.

* *

Diese Einstellung wird bei jeder Änderung der Spracheinstellung * automatisch angepasst. Standardwert ist in ISO-8601 das Komma (also * der ASCII-Wert 44). Mit Hilfe der bool'schen System-Property * "net.time4j.format.iso.decimal.dot" kann auch der Punkt * als alternativer Standardwert definiert werden.

*/ public static final AttributeKey DECIMAL_SEPARATOR = PredefinedKey.valueOf("DECIMAL_SEPARATOR", Character.class); /** *

Determines the pad char to be used if a formatted representation is * shorter than specified.

* *

Default value is the space. Numerical elements are not affected * by this attribute because they always use the zero digit as pad char.

*/ /*[deutsch] *

Legt das Füllzeichen in Textelementen fest, das verwendet wird, * wenn eine formatierte Darstellung kürzer als mindestens angegeben * ist.

* *

Standardwert ist das Leerzeichen. Numerische Elemente sind hiervon * nicht berührt, da sie immer die Nullziffer als Füllzeichen * verwenden.

*/ public static final AttributeKey PAD_CHAR = PredefinedKey.valueOf("PAD_CHAR", Character.class); /** *

Determines the pivot year for the representation of * two-digit-years.

* *

Default value is the year which is 20 years after the current * year. Example: If the pivot year has the value {@code 2034} then * a two-digit-year will be mapped to the range 1934-2033 such that * the last two digits are equal. This attribute must have at least * three digits an be positive else an exception will be thrown.

*/ /*[deutsch] *

Legt das Kippjahr zur zweistelligen Darstellung von Jahreselementen * fest.

* *

Standardwert ist das Jahr, das 20 Jahre nach dem aktuellen Jahr * liegt. Hat zum Beispiel das Kippjahr den Wert {@code 2034}, dann * wird eine zweistellige Jahresangabe auf das Intervall 1934-2033 * so abgebildet, daß die letzten zwei Ziffern gleich sind. * Kippjahresangaben müssen mindestens 3-stellig und positiv sein, * sonst wird ein solcher Versuch mit einer Ausnahme quittiert.

*/ public static final AttributeKey PIVOT_YEAR = PredefinedKey.valueOf("PIVOT_YEAR", Integer.class); /** *

Controls if any trailing unparsed characters will be * tolerated or not.

* *

Example:

* *
     *  ChronoFormatter formatter =
     *      ChronoFormatter.setUp(PlainTime.class, Locale.US)
     *      .addInteger(PlainTime.CLOCK_HOUR_OF_AMPM, 1, 2)
     *      .addLiteral(' ')
     *      .addText(PlainTime.AM_PM_OF_DAY)
     *      .padPrevious(3)
     *      .addFixedInteger(PlainTime.MINUTE_OF_HOUR, 2)
     *      .build()
     *      .with(Attributes.TRAILING_CHARACTERS, true);
     *  System.out.println(formatter.parse("5 PM 45xyz"));
     *  // Output: T17:45
     * 
* *

Default value: {@code false}

*/ /*[deutsch] *

Steuert, ob beim Parsen verbleibende Zeichen der Texteingabe * toleriert werden.

* *

Beispiel:

* *
     *  ChronoFormatter formatter =
     *      ChronoFormatter.setUp(PlainTime.class, Locale.US)
     *      .addInteger(PlainTime.CLOCK_HOUR_OF_AMPM, 1, 2)
     *      .addLiteral(' ')
     *      .addText(PlainTime.AM_PM_OF_DAY)
     *      .padPrevious(3)
     *      .addFixedInteger(PlainTime.MINUTE_OF_HOUR, 2)
     *      .build()
     *      .with(Attributes.TRAILING_CHARACTERS, true);
     *  System.out.println(formatter.parse("5 PM 45xyz"));
     *  // Output: T17:45
     * 
* *

Standardwert: {@code false}

*/ public static final AttributeKey TRAILING_CHARACTERS = PredefinedKey.valueOf("TRAILING_CHARACTERS", Boolean.class); /** *

Determines how many remaining chars in a given text are reserved * and cannot be consumed by the current format step.

* *

Default value is {@code 0}. This attribute can be used as sectional * attribute if an integer element is numerically processed. Such a * protected element will not consume any following chars and possibly * use the default value setting of the current formatter instead.

* *

Note: This attribute overrides any reserved area due to * adjacent digit parsing.

* * @since 2.0 * @see ChronoFormatter#withDefault */ /*[deutsch] *

Legt fest, wieviele der verbleibenden Zeichen in einem zu * interpretierenden Text reserviert und damit nicht vom aktuellen * Formatschritt konsumiert werden können.

* *

Standardwert ist {@code 0}. Dieses Attribut eignet sich als * sektionales Attribut, wenn ein Integer-Element numerisch * verarbeitet wird. So ein geschütztes Element wird keine * folgenden Zeichen konsumieren und eventuell den Standardwert * des aktuellen Formatierers verwenden.

* *

Hinweis: Dieses Attribut überlagert reservierte Ziffernbereiche, * die dem Modus adjacent digit parsing von nachgelagerten Elementen * mit fester Ziffernbreite zuzuschreiben sind.

* * @since 2.0 * @see ChronoFormatter#withDefault */ public static final AttributeKey PROTECTED_CHARACTERS = PredefinedKey.valueOf("PROTECTED_CHARACTERS", Integer.class); /** *

Gibt die Sprach- und Ländereinstellung an, die die * Sprachausgabe von chronologischen Texten (Beispiel Monatsnamen) * und andere Aspekte wie Wochennummerierungen steuert.

* *

Standardwert: {@code Locale.ROOT}.

*/ static final AttributeKey LOCALE = PredefinedKey.valueOf("_LOCALE", Locale.class); /** *

Steuert, ob eine optionale Sektion vorliegt, in der eventuelle Fehler * beim Parsen nicht zum Abbruch führen, sondern nur zum Ignorieren * der interpretierten Werte.

* *

Der führende Unterstrich im Namen zeigt die rein interne * Verwendung an. Standardwert: {@code false}

*/ static final AttributeKey OPTIONAL = PredefinedKey.valueOf("_OPTIONAL", Boolean.class); /** *

Zeigt die Ebene der optionalen Verarbeitungshierarchie an.

* *

Der führende Unterstrich im Namen zeigt die rein interne * Verwendung an. Standardwert: {@code 0}

*/ static final AttributeKey LEVEL = PredefinedKey.valueOf("_LEVEL", Integer.class); /** *

Identifiziert eine optionale Attributsektion.

* *

Der führende Unterstrich im Namen zeigt die rein interne * Verwendung an. Standardwert: {@code 0}

*/ static final AttributeKey SECTION = PredefinedKey.valueOf("_SECTION", Integer.class); private static final char ISO_DECIMAL_SEPARATOR = ( Boolean.getBoolean("net.time4j.format.iso.decimal.dot") ? '.' : ',' // Empfehlung des ISO-Standards ); private static final ConcurrentMap NUMBER_SYMBOL_CACHE = new ConcurrentHashMap(); private static final NumericalSymbols DEFAULT_NUMERICAL_SYMBOLS = new NumericalSymbols('0', ISO_DECIMAL_SEPARATOR); private static final AttributeQuery EMPTY = new Attributes.Builder().build(); //~ Instanzvariablen -------------------------------------------------- private final Map attributes; private final ChronoCondition printCondition; //~ Konstruktoren ----------------------------------------------------- private Attributes( Map map, ChronoCondition printCondition ) { super(); this.attributes = Collections.unmodifiableMap(new HashMap(map)); this.printCondition = printCondition; } //~ Methoden ---------------------------------------------------------- /** *

Represents an empty collection of format attributes.

* * @return empty attribute query */ /*[deutsch] *

Repräsentiert eine leere Menge von Formatattributen.

* * @return empty attribute query */ public static AttributeQuery empty() { return EMPTY; } @Override public boolean contains(AttributeKey key) { return this.attributes.containsKey(key.name()); } @Override public A get(AttributeKey key) { Object obj = this.attributes.get(key.name()); if (obj == null) { throw new NoSuchElementException(key.name()); } else { return key.type().cast(obj); } } @Override public A get( AttributeKey key, A defaultValue ) { Object obj = this.attributes.get(key.name()); if (obj == null) { return defaultValue; } else { return key.type().cast(obj); } } /** *

Compares all internal format attributes.

*/ /*[deutsch] *

Vergleicht auf Basis aller internen Formatattribute.

*/ @Override public boolean equals(Object obj) { if (this == obj) { return true; } else if (obj instanceof Attributes) { Attributes that = (Attributes) obj; return this.attributes.equals(that.attributes); } else { return false; } } /*[deutsch] *

Berechnet den Hash-Code.

*/ @Override public int hashCode() { return this.attributes.hashCode(); } /** *

Supports mainly debugging.

*/ /*[deutsch] *

Dient vorwiegend der Debugging-Unterstützung.

*/ @Override public String toString() { StringBuilder sb = new StringBuilder(this.attributes.size() * 32); sb.append(this.getClass().getName()); sb.append('['); sb.append(this.attributes); sb.append(']'); return sb.toString(); } /** *

Ermittelt die Sprach- und Ländereinstellung.

* *

Falls ein Bezug zu ISO-8601 ohne eine konkrete Sprache vorliegt, * liefert die Methode ein {@code Locale.ROOT}.

* * @return Locale (empty if related to ISO-8601, never {@code null}) * @see #LOCALE */ Locale getLocale() { return this.get(Attributes.LOCALE, Locale.ROOT); } /** *

Ermittelt eine Print-Bedingung.

* * @return print condition object maybe {@code null} */ ChronoCondition getCondition() { return this.printCondition; } /** *

Konstruiert einen {@code Builder} mit der angegebenen Sprach- und * Ländereinstellung.

* * @param locale Sprach- und Ländereinstellung * @return builder instance with some predefined localized attributes */ static Attributes.Builder createDefaults(Locale locale) { Attributes.Builder builder = new Attributes.Builder(); builder.setStandardAttributes(); builder.setLocale(locale); return builder; } //~ Innere Klassen ---------------------------------------------------- /** *

Builds a collection of format attributes.

*/ /*[deutsch] *

Baut eine Menge von Formatattributen.

*/ public static final class Builder { //~ Instanzvariablen ---------------------------------------------- private final Map attributes = new HashMap(); private ChronoCondition printCondition = null; //~ Konstruktoren ------------------------------------------------- /** *

Default constructor.

*/ /*[deutsch] *

Standard-Konstruktor.

*/ public Builder() { super(); } //~ Methoden ------------------------------------------------------ /** *

Sets the calendar type.

* * @param calendarType calendar type for resource lookup * @return this instance for method chaining */ /*[deutsch] *

Legt den Kalendertyp fest.

* * @param calendarType calendar type for resource lookup * @return this instance for method chaining */ public Builder setCalendarType(String calendarType) { this.setInternal(CALENDAR_TYPE, calendarType); return this; } /** *

Sets the language.

* * @param locale new language setting * @return this instance for method chaining * @see #LANGUAGE */ /*[deutsch] *

Setzt die Spracheinstellung.

* * @param locale new language setting * @return this instance for method chaining * @see #LANGUAGE */ public Builder setLanguage(Locale locale) { this.setInternal(LANGUAGE, locale); return this; } /** *

Sets the timezone reference.

* * @param tzid timezone id * @return this instance for method chaining * @see #TIMEZONE_ID */ /*[deutsch] *

Setzt die Zeitzonenreferenz.

* * @param tzid timezone id * @return this instance for method chaining * @see #TIMEZONE_ID */ public Builder setTimezone(TZID tzid) { this.setInternal(TIMEZONE_ID, tzid); return this; } /** *

Sets the timezone reference.

* * @param tzid timezone id * @return this instance for method chaining * @throws IllegalArgumentException if given timezone cannot be loaded * @see #TIMEZONE_ID * @since 1.1 */ /*[deutsch] *

Setzt die Zeitzonenreferenz.

* * @param tzid timezone id * @return this instance for method chaining * @throws IllegalArgumentException if given timezone cannot be loaded * @see #TIMEZONE_ID * @since 1.1 */ public Builder setTimezone(String tzid) { this.setTimezone(Timezone.of(tzid).getID()); return this; } /** *

Sets the system timezone reference.

* * @return this instance for method chaining * @see #TIMEZONE_ID * @see Timezone#ofSystem() */ /*[deutsch] *

Legt die Systemzeitzone als Zeitzonenreferenz fest.

* * @return this instance for method chaining * @see #TIMEZONE_ID * @see Timezone#ofSystem() */ public Builder setStdTimezone() { return this.setTimezone(Timezone.ofSystem().getID()); } /** *

Sets an attribute of {@code boolean}-type.

* * @param key attribute key * @param value attribute value * @return this instance for method chaining */ /*[deutsch] *

Setzt ein Formatattribut vom {@code boolean}-Typ.

* * @param key attribute key * @param value attribute value * @return this instance for method chaining */ public Builder set( AttributeKey key, boolean value ) { this.attributes.put(key.name(), Boolean.valueOf(value)); return this; } /** *

Sets an attribute of {@code int}-type.

* * @param key attribute key * @param value attribute value * @return this instance for method chaining * @throws IllegalArgumentException if an invalid pivot year is given */ /*[deutsch] *

Setzt ein Formatattribut vom {@code int}-Typ.

* * @param key attribute key * @param value attribute value * @return this instance for method chaining * @throws IllegalArgumentException if an invalid pivot year is given */ public Builder set( AttributeKey key, int value ) { if ( (key == Attributes.PIVOT_YEAR) && (value < 100) ) { throw new IllegalArgumentException( "Pivot year in far past not supported: " + value); } this.attributes.put(key.name(), Integer.valueOf(value)); return this; } /** *

Sets an attribute of {@code char}-type.

* * @param key attribute key * @param value attribute value * @return this instance for method chaining */ /*[deutsch] *

Setzt ein Formatattribut vom {@code char}-Typ.

* * @param key attribute key * @param value attribute value * @return this instance for method chaining */ public Builder set( AttributeKey key, char value ) { this.attributes.put(key.name(), Character.valueOf(value)); return this; } /** *

Sets an attribute of {@code enum}-type.

* * @param
generic type of attribute * @param key attribute key * @param value attribute value * @return this instance for method chaining */ /*[deutsch] *

Setzt ein Formatattribut vom {@code enum}-Typ.

* * @param
generic type of attribute * @param key attribute key * @param value attribute value * @return this instance for method chaining */ public > Builder set( AttributeKey key, A value ) { if (value == null) { throw new NullPointerException("Missing attribute value."); } else if (!(value instanceof Enum)) { throw new ClassCastException( // Schutz gegen raw-type-Fehler "Enum expected, but found: " + value); } this.attributes.put(key.name(), value); Object compare = key; // stellt JDK-6 zufrieden if (compare == Attributes.LENIENCY) { switch (Leniency.class.cast(value)) { case STRICT: this.set(Attributes.PARSE_CASE_INSENSITIVE, false); this.set(Attributes.PARSE_PARTIAL_COMPARE, false); this.set(Attributes.TRAILING_CHARACTERS, false); break; case SMART: this.set(Attributes.PARSE_CASE_INSENSITIVE, true); this.set(Attributes.PARSE_PARTIAL_COMPARE, false); this.set(Attributes.TRAILING_CHARACTERS, false); break; case LAX: this.set(Attributes.PARSE_CASE_INSENSITIVE, true); this.set(Attributes.PARSE_PARTIAL_COMPARE, true); this.set(Attributes.TRAILING_CHARACTERS, true); break; default: throw new UnsupportedOperationException(value.name()); } } return this; } /** *

Accepts all given attributes.

* *

If an attribute already exists then it will * be overridden.

* * @param attributes format attributes * @return this instance for method chaining */ /*[deutsch] *

Übernimmt alle angegebenen Attribute.

* *

Existiert ein Formatattribut schon, wird es * überschrieben.

* * @param attributes format attributes * @return this instance for method chaining */ public Builder setAll(Attributes attributes) { this.attributes.putAll(attributes.attributes); return this; } /** *

Removes the specified attribute.

* * @param key attribute key to be removed * @return this instance for method chaining * @throws IllegalArgumentException if given attribute is internal */ /*[deutsch] *

Entfernt das angegebene Attribut.

* * @param key attribute key to be removed * @return this instance for method chaining * @throws IllegalArgumentException if given attribute is internal */ public Builder remove(AttributeKey key) { String name = key.name(); if (name.startsWith("_")) { throw new IllegalArgumentException( "Internal attribute cannot be removed: " + name); } this.attributes.remove(name); return this; } /** *

Creates a new unmodifiable collection of format attributes.

* * @return new instance of {@code Attributes} */ /*[deutsch] *

Erzeugt eine neue unveränderliche Instanz der * Formatattribute.

* * @return new instance of {@code Attributes} */ public Attributes build() { return new Attributes(this.attributes, this.printCondition); } /** *

Setzt die Sprach- und Ländereinstellung.

* *

Die Attribute {@link #ZERO_DIGIT}, {@link #DECIMAL_SEPARATOR} * und {@link #LANGUAGE} werden automatisch mit angepasst.

* * @param locale new language and country setting * @return this instance for method chaining * @see #LOCALE */ Builder setLocale(Locale locale) { if ( locale.getLanguage().isEmpty() && locale.getCountry().isEmpty() ) { locale = Locale.ROOT; this.set(ZERO_DIGIT, '0'); this.set(DECIMAL_SEPARATOR, ISO_DECIMAL_SEPARATOR); } else { NumericalSymbols symbols = NUMBER_SYMBOL_CACHE.get(locale); if (symbols == null) { symbols = DEFAULT_NUMERICAL_SYMBOLS; for (Locale test : NUMBER_SYMBOLS.getAvailableLocales()) { if (locale.equals(test)) { symbols = new NumericalSymbols( NUMBER_SYMBOLS.getZeroDigit(locale), NUMBER_SYMBOLS.getDecimalSeparator(locale) ); break; } } NumericalSymbols old = NUMBER_SYMBOL_CACHE.putIfAbsent(locale, symbols); if (old != null) { symbols = old; } } this.set(ZERO_DIGIT, symbols.zeroDigit); this.set(DECIMAL_SEPARATOR, symbols.decimalSeparator); } this.setInternal(LOCALE, locale); this.setInternal(LANGUAGE, locale); return this; } /** *

Setzt eine Print-Bedingung.

* * @param printCondition condition object */ void setCondition(ChronoCondition printCondition) { this.printCondition = printCondition; } private Builder setStandardAttributes() { this.set(LENIENCY, Leniency.SMART); this.set(TEXT_WIDTH, TextWidth.WIDE); this.set(OUTPUT_CONTEXT, OutputContext.FORMAT); this.set(PAD_CHAR, ' '); return this; } private
void setInternal( AttributeKey key, A value ) { if (value == null) { throw new NullPointerException("Missing attribute value."); } this.attributes.put(key.name(), value); } } private static class NumericalSymbols { //~ Instanzvariablen ---------------------------------------------- private final char zeroDigit; private final char decimalSeparator; //~ Konstruktoren ------------------------------------------------- NumericalSymbols( char zeroDigit, char decimalSeparator ) { super(); this.zeroDigit = zeroDigit; this.decimalSeparator = decimalSeparator; } } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy