blob: 93a156b7e24f328a723ce204957ffc88f3f5cb5f [file] [log] [blame]
/*
* Copyright (C) 2014 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.text.style;
import java.text.NumberFormat;
import java.util.Locale;
import android.os.Parcel;
import android.os.PersistableBundle;
import android.text.ParcelableSpan;
import android.text.TextUtils;
/**
* A span that supplies additional meta-data for the associated text intended
* for text-to-speech engines. If the text is being processed by a
* text-to-speech engine, the engine may use the data in this span in addition
* to or instead of its associated text.
*
* Each instance of a TtsSpan has a type, for example {@link #TYPE_DATE}
* or {@link #TYPE_MEASURE}. And a list of arguments, provided as
* key-value pairs in a bundle.
*
* The inner classes are there for convenience and provide builders for each
* TtsSpan type.
*/
public class TtsSpan implements ParcelableSpan {
private final String mType;
private final PersistableBundle mArgs;
/**
* This span type can be used to add morphosyntactic features to the text it
* spans over, or synthesize a something else than the spanned text. Use
* the argument {@link #ARG_TEXT} to set a different text.
* Accepts the arguments {@link #ARG_GENDER},
* {@link #ARG_ANIMACY}, {@link #ARG_MULTIPLICITY} and
* {@link #ARG_CASE}.
*/
public static final String TYPE_TEXT = "android.type.text";
/**
* The text associated with this span is a cardinal. Must include the
* number to be synthesized with {@link #ARG_NUMBER}.
* Also accepts the arguments {@link #ARG_GENDER},
* {@link #ARG_ANIMACY}, {@link #ARG_MULTIPLICITY} and
* {@link #ARG_CASE}.
*/
public static final String TYPE_CARDINAL = "android.type.cardinal";
/**
* The text associated with this span is an ordinal. Must include the
* number to be synthesized with {@link #ARG_NUMBER}.
* Also accepts the arguments {@link #ARG_GENDER},
* {@link #ARG_ANIMACY}, {@link #ARG_MULTIPLICITY} and
* {@link #ARG_CASE}.
*/
public static final String TYPE_ORDINAL = "android.type.ordinal";
/**
* The text associated with this span is a decimal number. Must include the
* number to be synthesized with {@link #ARG_INTEGER_PART} and
* {@link #ARG_FRACTIONAL_PART}.
* Also accepts the arguments {@link #ARG_GENDER},
* {@link #ARG_ANIMACY}, {@link #ARG_MULTIPLICITY} and
* {@link #ARG_CASE}.
*/
public static final String TYPE_DECIMAL = "android.type.decimal";
/**
* The text associated with this span is a fractional number. Must include
* the number to be synthesized with {@link #ARG_NUMERATOR} and
* {@link #ARG_DENOMINATOR}. {@link #ARG_INTEGER_PART} is optional
* Also accepts the arguments {@link #ARG_GENDER},
* {@link #ARG_ANIMACY}, {@link #ARG_MULTIPLICITY} and
* {@link #ARG_CASE}.
*/
public static final String TYPE_FRACTION = "android.type.fraction";
/**
* The text associated with this span is a measure, consisting of a number
* and a unit. The number can be a cardinal, decimal or a fraction. Set the
* number with the same arguments as {@link #TYPE_CARDINAL},
* {@link #TYPE_DECIMAL} or {@link #TYPE_FRACTION}. The unit can be
* specified with {@link #ARG_UNIT}.
* Also accepts the arguments {@link #ARG_GENDER},
* {@link #ARG_ANIMACY}, {@link #ARG_MULTIPLICITY} and
* {@link #ARG_CASE}.
*/
public static final String TYPE_MEASURE = "android.type.measure";
/**
* The text associated with this span is a time, consisting of a number of
* hours and minutes, specified with {@link #ARG_HOURS} and
* {@link #ARG_MINUTES}.
* Also accepts the arguments {@link #ARG_GENDER},
* {@link #ARG_ANIMACY}, {@link #ARG_MULTIPLICITY} and
* {@link #ARG_CASE}.
*/
public static final String TYPE_TIME = "android.type.time";
/**
* The text associated with this span is a date. At least one of the
* arguments {@link #ARG_MONTH} and {@link #ARG_YEAR} has to be provided.
* The argument {@link #ARG_DAY} is optional if {@link #ARG_MONTH} is set.
* The argument {@link #ARG_WEEKDAY} is optional if {@link #ARG_DAY} is set.
* Also accepts the arguments {@link #ARG_GENDER}, {@link #ARG_ANIMACY},
* {@link #ARG_MULTIPLICITY} and {@link #ARG_CASE}.
*/
public static final String TYPE_DATE = "android.type.date";
/**
* The text associated with this span is a telephone number. The argument
* {@link #ARG_NUMBER_PARTS} is required. {@link #ARG_COUNTRY_CODE} and
* {@link #ARG_EXTENSION} are optional.
* Also accepts the arguments {@link #ARG_GENDER}, {@link #ARG_ANIMACY},
* {@link #ARG_MULTIPLICITY} and {@link #ARG_CASE}.
*/
public static final String TYPE_TELEPHONE = "android.type.telephone";
/**
* The text associated with this span is a URI (can be used for URLs and
* email addresses). The full schema for URLs, which email addresses can
* effectively be seen as a subset of, is:
* protocol://username:password@domain:port/path?query_string#fragment_id
* Hence populating just username and domain will read as an email address.
* All arguments are optional, but at least one has to be provided:
* {@link #ARG_PROTOCOL}, {@link #ARG_USERNAME}, {@link #ARG_PASSWORD},
* {@link #ARG_DOMAIN}, {@link #ARG_PORT}, {@link #ARG_PATH},
* {@link #ARG_QUERY_STRING} and {@link #ARG_FRAGMENT_ID}.
* Also accepts the arguments {@link #ARG_GENDER}, {@link #ARG_ANIMACY},
* {@link #ARG_MULTIPLICITY} and {@link #ARG_CASE}.
*/
public static final String TYPE_ELECTRONIC = "android.type.electronic";
/**
* The text associated with this span is an amount of money. Set the amount
* with the same arguments as {@link #TYPE_DECIMAL}.
* {@link #ARG_CURRENCY} is used to set the currency. {@link #ARG_QUANTITY}
* is optional.
* Also accepts the arguments {@link #ARG_GENDER}, {@link #ARG_ANIMACY},
* {@link #ARG_MULTIPLICITY} and {@link #ARG_CASE}.
*/
public static final String TYPE_MONEY = "android.type.money";
/**
* The text associated with this span is a series of digits that have to be
* read sequentially. The digits can be set with {@link #ARG_DIGITS}.
* Also accepts the arguments {@link #ARG_GENDER}, {@link #ARG_ANIMACY},
* {@link #ARG_MULTIPLICITY} and {@link #ARG_CASE}.
*/
public static final String TYPE_DIGITS = "android.type.digits";
/**
* The text associated with this span is a series of characters that have to
* be read verbatim. The engine will attempt to read out any character like
* punctuation but excluding whitespace. {@link #ARG_VERBATIM} is required.
* Also accepts the arguments {@link #ARG_GENDER},
* {@link #ARG_ANIMACY}, {@link #ARG_MULTIPLICITY} and {@link #ARG_CASE}.
*/
public static final String TYPE_VERBATIM = "android.type.verbatim";
/**
* String argument supplying gender information. Can be any of
* {@link #GENDER_NEUTRAL}, {@link #GENDER_MALE} and
* {@link #GENDER_FEMALE}.
*/
public static final String ARG_GENDER = "android.arg.gender";
public static final String GENDER_NEUTRAL = "android.neutral";
public static final String GENDER_MALE = "android.male";
public static final String GENDER_FEMALE = "android.female";
/**
* String argument supplying animacy information. Can be
* {@link #ANIMACY_ANIMATE} or
* {@link #ANIMACY_INANIMATE}
*/
public static final String ARG_ANIMACY = "android.arg.animacy";
public static final String ANIMACY_ANIMATE = "android.animate";
public static final String ANIMACY_INANIMATE = "android.inanimate";
/**
* String argument supplying multiplicity information. Can be any of
* {@link #MULTIPLICITY_SINGLE}, {@link #MULTIPLICITY_DUAL} and
* {@link #MULTIPLICITY_PLURAL}
*/
public static final String ARG_MULTIPLICITY = "android.arg.multiplicity";
public static final String MULTIPLICITY_SINGLE = "android.single";
public static final String MULTIPLICITY_DUAL = "android.dual";
public static final String MULTIPLICITY_PLURAL = "android.plural";
/**
* String argument supplying case information. Can be any of
* {@link #CASE_NOMINATIVE}, {@link #CASE_ACCUSATIVE}, {@link #CASE_DATIVE},
* {@link #CASE_ABLATIVE}, {@link #CASE_GENITIVE}, {@link #CASE_VOCATIVE},
* {@link #CASE_LOCATIVE} and {@link #CASE_INSTRUMENTAL}
*/
public static final String ARG_CASE = "android.arg.case";
public static final String CASE_NOMINATIVE = "android.nominative";
public static final String CASE_ACCUSATIVE = "android.accusative";
public static final String CASE_DATIVE = "android.dative";
public static final String CASE_ABLATIVE = "android.ablative";
public static final String CASE_GENITIVE = "android.genitive";
public static final String CASE_VOCATIVE = "android.vocative";
public static final String CASE_LOCATIVE = "android.locative";
public static final String CASE_INSTRUMENTAL = "android.instrumental";
/**
* String supplying the text to be synthesized. The synthesizer is free
* to decide how to interpret the text.
* Can be used with {@link #TYPE_TEXT}.
*/
public static final String ARG_TEXT = "android.arg.text";
/**
* Argument used to specify a whole number. The value can be a string of
* digits of any size optionally prefixed with a - or +.
* Can be used with {@link #TYPE_CARDINAL} and {@link #TYPE_ORDINAL}.
*/
public static final String ARG_NUMBER = "android.arg.number";
/**
* Argument used to specify the integer part of a decimal or fraction. The
* value can be a string of digits of any size optionally prefixed with
* a - or +.
* Can be used with {@link #TYPE_DECIMAL} and {@link #TYPE_FRACTION}.
*/
public static final String ARG_INTEGER_PART = "android.arg.integer_part";
/**
* Argument used to specify the fractional part of a decimal. The value can
* be a string of digits of any size.
* Can be used with {@link #TYPE_DECIMAL}.
*/
public static final String ARG_FRACTIONAL_PART =
"android.arg.fractional_part";
/**
* Argument used to choose the suffix (thousand, million, etc) that is used
* to pronounce large amounts of money. For example it can be used to
* disambiguate between "two thousand five hundred dollars" and
* "two point five thousand dollars".
* If implemented, engines should support at least "1000", "1000000",
* "1000000000" and "1000000000000".
* Example: if the {@link #ARG_INTEGER_PART} argument is "10", the
* {@link #ARG_FRACTIONAL_PART} argument is "4", the {@link #ARG_QUANTITY}
* argument is "1000" and the {@link #ARG_CURRENCY} argument is "usd", the
* TTS engine may pronounce the span as "ten point four thousand dollars".
* With the same example but with the quantity set as "1000000" the TTS
* engine may pronounce the span as "ten point four million dollars".
* Can be used with {@link #TYPE_MONEY}.
*/
public static final String ARG_QUANTITY =
"android.arg.quantity";
/**
* Argument used to specify the numerator of a fraction. The value can be a
* string of digits of any size optionally prefixed with a - or +.
* Can be used with {@link #TYPE_FRACTION}.
*/
public static final String ARG_NUMERATOR = "android.arg.numerator";
/**
* Argument used to specify the denominator of a fraction. The value can be
* a string of digits of any size optionally prefixed with a + or -.
* Can be used with {@link #TYPE_FRACTION}.
*/
public static final String ARG_DENOMINATOR = "android.arg.denominator";
/**
* Argument used to specify the unit of a measure. The unit should always be
* specified in English singular form. Prefixes may be used. Engines will do
* their best to pronounce them correctly in the language used. Engines are
* expected to at least support the most common ones like "meter", "second",
* "degree celsius" and "degree fahrenheit" with some common prefixes like
* "milli" and "kilo".
* Can be used with {@link #TYPE_MEASURE}.
*/
public static final String ARG_UNIT = "android.arg.unit";
/**
* Argument used to specify the hours of a time. The hours should be
* provided as an integer in the range from 0 up to and including 24.
* Can be used with {@link #TYPE_TIME}.
*/
public static final String ARG_HOURS = "android.arg.hours";
/**
* Argument used to specify the minutes of a time. The hours should be
* provided as an integer in the range from 0 up to and including 59.
* Can be used with {@link #TYPE_TIME}.
*/
public static final String ARG_MINUTES = "android.arg.minutes";
/**
* Argument used to specify the weekday of a date. The value should be
* provided as an integer and can be any of {@link #WEEKDAY_SUNDAY},
* {@link #WEEKDAY_MONDAY}, {@link #WEEKDAY_TUESDAY},
* {@link #WEEKDAY_WEDNESDAY}, {@link #WEEKDAY_THURSDAY},
* {@link #WEEKDAY_FRIDAY} and {@link #WEEKDAY_SATURDAY}.
* Can be used with {@link #TYPE_DATE}.
*/
public static final String ARG_WEEKDAY = "android.arg.weekday";
public static final int WEEKDAY_SUNDAY = 1;
public static final int WEEKDAY_MONDAY = 2;
public static final int WEEKDAY_TUESDAY = 3;
public static final int WEEKDAY_WEDNESDAY = 4;
public static final int WEEKDAY_THURSDAY = 5;
public static final int WEEKDAY_FRIDAY = 6;
public static final int WEEKDAY_SATURDAY = 7;
/**
* Argument used to specify the day of the month of a date. The value should
* be provided as an integer in the range from 1 up to and including 31.
* Can be used with {@link #TYPE_DATE}.
*/
public static final String ARG_DAY = "android.arg.day";
/**
* Argument used to specify the month of a date. The value should be
* provided as an integer and can be any of {@link #MONTH_JANUARY},
* {@link #MONTH_FEBRUARY}, {@link #MONTH_MARCH}, {@link #MONTH_APRIL},
* {@link #MONTH_MAY}, {@link #MONTH_JUNE}, {@link #MONTH_JULY},
* {@link #MONTH_AUGUST}, {@link #MONTH_SEPTEMBER}, {@link #MONTH_OCTOBER},
* {@link #MONTH_NOVEMBER} and {@link #MONTH_DECEMBER}.
* Can be used with {@link #TYPE_DATE}.
*/
public static final String ARG_MONTH = "android.arg.month";
public static final int MONTH_JANUARY = 0;
public static final int MONTH_FEBRUARY = 1;
public static final int MONTH_MARCH = 2;
public static final int MONTH_APRIL = 3;
public static final int MONTH_MAY = 4;
public static final int MONTH_JUNE = 5;
public static final int MONTH_JULY = 6;
public static final int MONTH_AUGUST = 7;
public static final int MONTH_SEPTEMBER = 8;
public static final int MONTH_OCTOBER = 9;
public static final int MONTH_NOVEMBER = 10;
public static final int MONTH_DECEMBER = 11;
/**
* Argument used to specify the year of a date. The value should be provided
* as a positive integer.
* Can be used with {@link #TYPE_DATE}.
*/
public static final String ARG_YEAR = "android.arg.year";
/**
* Argument used to specify the country code of a telephone number. Can be
* a string of digits optionally prefixed with a "+".
* Can be used with {@link #TYPE_TELEPHONE}.
*/
public static final String ARG_COUNTRY_CODE = "android.arg.country_code";
/**
* Argument used to specify the main number part of a telephone number. Can
* be a string of digits where the different parts of the telephone number
* can be separated with a space, '-', '/' or '.'.
* Can be used with {@link #TYPE_TELEPHONE}.
*/
public static final String ARG_NUMBER_PARTS = "android.arg.number_parts";
/**
* Argument used to specify the extension part of a telephone number. Can be
* a string of digits.
* Can be used with {@link #TYPE_TELEPHONE}.
*/
public static final String ARG_EXTENSION = "android.arg.extension";
/**
* Argument used to specify the protocol of a URI. Examples are "http" and
* "ftp".
* Can be used with {@link #TYPE_ELECTRONIC}.
*/
public static final String ARG_PROTOCOL = "android.arg.protocol";
/**
* Argument used to specify the username part of a URI. Should be set as a
* string.
* Can be used with {@link #TYPE_ELECTRONIC}.
*/
public static final String ARG_USERNAME = "android.arg.username";
/**
* Argument used to specify the password part of a URI. Should be set as a
* string.
* Can be used with {@link #TYPE_ELECTRONIC}.
*/
public static final String ARG_PASSWORD = "android.arg.password";
/**
* Argument used to specify the domain part of a URI. For example
* "source.android.com".
* Can be used with {@link #TYPE_ELECTRONIC}.
*/
public static final String ARG_DOMAIN = "android.arg.domain";
/**
* Argument used to specify the port number of a URI. Should be specified as
* an integer.
* Can be used with {@link #TYPE_ELECTRONIC}.
*/
public static final String ARG_PORT = "android.arg.port";
/**
* Argument used to specify the path part of a URI. For example
* "source/index.html".
* Can be used with {@link #TYPE_ELECTRONIC}.
*/
public static final String ARG_PATH = "android.arg.path";
/**
* Argument used to specify the query string of a URI. For example
* "arg=value&argtwo=value".
* Can be used with {@link #TYPE_ELECTRONIC}.
*/
public static final String ARG_QUERY_STRING = "android.arg.query_string";
/**
* Argument used to specify the fragment id of a URI. Should be specified as
* a string.
* Can be used with {@link #TYPE_ELECTRONIC}.
*/
public static final String ARG_FRAGMENT_ID = "android.arg.fragment_id";
/**
* Argument used to specify the currency. Should be a ISO4217 currency code,
* e.g. "USD".
* Can be used with {@link #TYPE_MONEY}.
*/
public static final String ARG_CURRENCY = "android.arg.money";
/**
* Argument used to specify a string of digits.
* Can be used with {@link #TYPE_DIGITS}.
*/
public static final String ARG_DIGITS = "android.arg.digits";
/**
* Argument used to specify a string where the characters are read verbatim,
* except whitespace.
* Can be used with {@link #TYPE_VERBATIM}.
*/
public static final String ARG_VERBATIM = "android.arg.verbatim";
public TtsSpan(String type, PersistableBundle args) {
mType = type;
mArgs = args;
}
public TtsSpan(Parcel src) {
mType = src.readString();
mArgs = src.readPersistableBundle();
}
/**
* Returns the type.
* @return The type of this instance.
*/
public String getType() {
return mType;
}
/**
* Returns a bundle of the arguments set.
* @return The bundle of the arguments set.
*/
public PersistableBundle getArgs() {
return mArgs;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
writeToParcelInternal(dest, flags);
}
/** @hide */
public void writeToParcelInternal(Parcel dest, int flags) {
dest.writeString(mType);
dest.writePersistableBundle(mArgs);
}
@Override
public int getSpanTypeId() {
return getSpanTypeIdInternal();
}
/** @hide */
public int getSpanTypeIdInternal() {
return TextUtils.TTS_SPAN;
}
/**
* A simple builder for TtsSpans.
* This builder can be used directly, but the more specific subclasses of
* this builder like {@link TtsSpan.TextBuilder} and
* {@link TtsSpan.CardinalBuilder} are likely more useful.
*
* This class uses generics so methods from this class can return instances
* of its child classes, resulting in a fluent API (CRTP pattern).
*/
public static class Builder<C extends Builder<?>> {
// Holds the type of this class.
private final String mType;
// Holds the arguments of this class. It only stores objects of type
// String, Integer and Long.
private PersistableBundle mArgs = new PersistableBundle();
public Builder(String type) {
mType = type;
}
/**
* Returns a TtsSpan built from the parameters set by the setter
* methods.
* @return A TtsSpan built with parameters of this builder.
*/
public TtsSpan build() {
return new TtsSpan(mType, mArgs);
}
/**
* Sets an argument to a string value.
* @param arg The argument name.
* @param value The value the argument should be set to.
* @return This instance.
*/
@SuppressWarnings("unchecked")
public C setStringArgument(String arg, String value) {
mArgs.putString(arg, value);
return (C) this;
}
/**
* Sets an argument to an int value.
* @param arg The argument name.
* @param value The value the argument should be set to.
*/
@SuppressWarnings("unchecked")
public C setIntArgument(String arg, int value) {
mArgs.putInt(arg, value);
return (C) this;
}
/**
* Sets an argument to a long value.
* @param arg The argument name.
* @param value The value the argument should be set to.
*/
@SuppressWarnings("unchecked")
public C setLongArgument(String arg, long value) {
mArgs.putLong(arg, value);
return (C) this;
}
}
/**
* A builder for TtsSpans, has setters for morphosyntactic features.
* This builder can be used directly, but the more specific subclasses of
* this builder like {@link TtsSpan.TextBuilder} and
* {@link TtsSpan.CardinalBuilder} are likely more useful.
*/
public static class SemioticClassBuilder<C extends SemioticClassBuilder<?>>
extends Builder<C> {
public SemioticClassBuilder(String type) {
super(type);
}
/**
* Sets the gender information for this instance.
* @param gender Can any of {@link #GENDER_NEUTRAL},
* {@link #GENDER_MALE} and {@link #GENDER_FEMALE}.
* @return This instance.
*/
public C setGender(String gender) {
return setStringArgument(TtsSpan.ARG_GENDER, gender);
}
/**
* Sets the animacy information for this instance.
* @param animacy Can be any of {@link #ANIMACY_ANIMATE} and
* {@link #ANIMACY_INANIMATE}.
* @return This instance.
*/
public C setAnimacy(String animacy) {
return setStringArgument(TtsSpan.ARG_ANIMACY, animacy);
}
/**
* Sets the multiplicity information for this instance.
* @param multiplicity Can be any of
* {@link #MULTIPLICITY_SINGLE}, {@link #MULTIPLICITY_DUAL} and
* {@link #MULTIPLICITY_PLURAL}.
* @return This instance.
*/
public C setMultiplicity(String multiplicity) {
return setStringArgument(TtsSpan.ARG_MULTIPLICITY, multiplicity);
}
/**
* Sets the grammatical case information for this instance.
* @param grammaticalCase Can be any of {@link #CASE_NOMINATIVE},
* {@link #CASE_ACCUSATIVE}, {@link #CASE_DATIVE},
* {@link #CASE_ABLATIVE}, {@link #CASE_GENITIVE},
* {@link #CASE_VOCATIVE}, {@link #CASE_LOCATIVE} and
* {@link #CASE_INSTRUMENTAL}.
* @return This instance.
*/
public C setCase(String grammaticalCase) {
return setStringArgument(TtsSpan.ARG_CASE, grammaticalCase);
}
}
/**
* A builder for TtsSpans of type {@link #TYPE_TEXT}.
*/
public static class TextBuilder extends SemioticClassBuilder<TextBuilder> {
/**
* Creates a builder for a TtsSpan of type {@link #TYPE_TEXT}.
*/
public TextBuilder() {
super(TtsSpan.TYPE_TEXT);
}
/**
* Creates a TtsSpan of type {@link #TYPE_TEXT} and sets the
* {@link #ARG_TEXT} argument.
* @param text The text to be synthesized.
* @see #setText(String)
*/
public TextBuilder(String text) {
this();
setText(text);
}
/**
* Sets the {@link #ARG_TEXT} argument, the text to be synthesized.
* @param text The string that will be synthesized.
* @return This instance.
*/
public TextBuilder setText(String text) {
return setStringArgument(TtsSpan.ARG_TEXT, text);
}
}
/**
* A builder for TtsSpans of type {@link #TYPE_CARDINAL}.
*/
public static class CardinalBuilder
extends SemioticClassBuilder<CardinalBuilder> {
/**
* Creates a builder for a TtsSpan of type {@link #TYPE_CARDINAL}.
*/
public CardinalBuilder() {
super(TtsSpan.TYPE_CARDINAL);
}
/**
* Creates a TtsSpan of type {@link #TYPE_CARDINAL} and sets the
* {@link #ARG_NUMBER} argument.
* @param number The number to synthesize.
* @see #setNumber(long)
*/
public CardinalBuilder(long number) {
this();
setNumber(number);
}
/**
* Creates a TtsSpan of type {@link #TYPE_CARDINAL} and sets the
* {@link #ARG_NUMBER} argument.
* @param number The number to synthesize.
* @see #setNumber(String)
*/
public CardinalBuilder(String number) {
this();
setNumber(number);
}
/**
* Convenience method that converts the number to a String and set it to
* the value for {@link #ARG_NUMBER}.
* @param number The number that will be synthesized.
* @return This instance.
*/
public CardinalBuilder setNumber(long number) {
return setNumber(String.valueOf(number));
}
/**
* Sets the {@link #ARG_NUMBER} argument.
* @param number A non-empty string of digits with an optional
* leading + or -.
* @return This instance.
*/
public CardinalBuilder setNumber(String number) {
return setStringArgument(TtsSpan.ARG_NUMBER, number);
}
}
/**
* A builder for TtsSpans of type {@link #TYPE_ORDINAL}.
*/
public static class OrdinalBuilder
extends SemioticClassBuilder<OrdinalBuilder> {
/**
* Creates a builder for a TtsSpan of type {@link #TYPE_ORDINAL}.
*/
public OrdinalBuilder() {
super(TtsSpan.TYPE_ORDINAL);
}
/**
* Creates a TtsSpan of type {@link #TYPE_ORDINAL} and sets the
* {@link #ARG_NUMBER} argument.
* @param number The ordinal number to synthesize.
* @see #setNumber(long)
*/
public OrdinalBuilder(long number) {
this();
setNumber(number);
}
/**
* Creates a TtsSpan of type {@link #TYPE_ORDINAL} and sets the
* {@link #ARG_NUMBER} argument.
* @param number The number to synthesize.
* @see #setNumber(String)
*/
public OrdinalBuilder(String number) {
this();
setNumber(number);
}
/**
* Convenience method that converts the number to a String and sets it
* to the value for {@link #ARG_NUMBER}.
* @param number The ordinal number that will be synthesized.
* @return This instance.
*/
public OrdinalBuilder setNumber(long number) {
return setNumber(String.valueOf(number));
}
/**
* Sets the {@link #ARG_NUMBER} argument.
* @param number A non-empty string of digits with an optional
* leading + or -.
* @return This instance.
*/
public OrdinalBuilder setNumber(String number) {
return setStringArgument(TtsSpan.ARG_NUMBER, number);
}
}
/**
* A builder for TtsSpans of type {@link #TYPE_DECIMAL}.
*/
public static class DecimalBuilder
extends SemioticClassBuilder<DecimalBuilder> {
/**
* Creates a builder for a TtsSpan of type {@link #TYPE_DECIMAL}.
*/
public DecimalBuilder() {
super(TtsSpan.TYPE_DECIMAL);
}
/**
* Creates a TtsSpan of type {@link #TYPE_DECIMAL} and sets the
* {@link #ARG_INTEGER_PART} and {@link #ARG_FRACTIONAL_PART} arguments.
* @see {@link #setArgumentsFromDouble(double, int, int)
*/
public DecimalBuilder(double number,
int minimumFractionDigits,
int maximumFractionDigits) {
this();
setArgumentsFromDouble(number,
minimumFractionDigits,
maximumFractionDigits);
}
/**
* Creates a TtsSpan of type {@link #TYPE_DECIMAL} and sets the
* {@link #ARG_INTEGER_PART} and {@link #ARG_FRACTIONAL_PART} arguments.
*/
public DecimalBuilder(String integerPart, String fractionalPart) {
this();
setIntegerPart(integerPart);
setFractionalPart(fractionalPart);
}
/**
* Convenience method takes a double and a maximum number of fractional
* digits, it sets the {@link #ARG_INTEGER_PART} and
* {@link #ARG_FRACTIONAL_PART} arguments.
* @param number The number to be synthesized.
* @param minimumFractionDigits The minimum number of fraction digits
* that are pronounced.
* @param maximumFractionDigits The maximum number of fraction digits
* that are pronounced. If maximumFractionDigits <
* minimumFractionDigits then minimumFractionDigits will be assumed
* to be equal to maximumFractionDigits.
* @return This instance.
*/
public DecimalBuilder setArgumentsFromDouble(
double number,
int minimumFractionDigits,
int maximumFractionDigits) {
// Format double.
NumberFormat formatter = NumberFormat.getInstance(Locale.US);
formatter.setMinimumFractionDigits(maximumFractionDigits);
formatter.setMaximumFractionDigits(maximumFractionDigits);
formatter.setGroupingUsed(false);
String str = formatter.format(number);
// Split at decimal point.
int i = str.indexOf('.');
if (i >= 0) {
setIntegerPart(str.substring(0, i));
setFractionalPart(str.substring(i + 1));
} else {
setIntegerPart(str);
}
return this;
}
/**
* Convenience method that converts the number to a String and sets it
* to the value for {@link #ARG_INTEGER_PART}.
* @param integerPart The integer part of the decimal.
* @return This instance.
*/
public DecimalBuilder setIntegerPart(long integerPart) {
return setIntegerPart(String.valueOf(integerPart));
}
/**
* Sets the {@link #ARG_INTEGER_PART} argument.
* @param integerPart A non-empty string of digits with an optional
* leading + or -.
* @return This instance.
*/
public DecimalBuilder setIntegerPart(String integerPart) {
return setStringArgument(TtsSpan.ARG_INTEGER_PART, integerPart);
}
/**
* Sets the {@link #ARG_FRACTIONAL_PART} argument.
* @param fractionalPart A non-empty string of digits.
* @return This instance.
*/
public DecimalBuilder setFractionalPart(String fractionalPart) {
return setStringArgument(TtsSpan.ARG_FRACTIONAL_PART,
fractionalPart);
}
}
/**
* A builder for TtsSpans of type {@link #TYPE_FRACTION}.
*/
public static class FractionBuilder
extends SemioticClassBuilder<FractionBuilder> {
/**
* Creates a builder for a TtsSpan of type {@link #TYPE_FRACTION}.
*/
public FractionBuilder() {
super(TtsSpan.TYPE_FRACTION);
}
/**
* Creates a TtsSpan of type {@link #TYPE_FRACTION} and sets the
* {@link #ARG_INTEGER_PART}, {@link #ARG_NUMERATOR}, and
* {@link #ARG_DENOMINATOR} arguments.
*/
public FractionBuilder(long integerPart,
long numerator,
long denominator) {
this();
setIntegerPart(integerPart);
setNumerator(numerator);
setDenominator(denominator);
}
/**
* Convenience method that converts the integer to a String and sets the
* argument {@link #ARG_NUMBER}.
* @param integerPart The integer part.
* @return This instance.
*/
public FractionBuilder setIntegerPart(long integerPart) {
return setIntegerPart(String.valueOf(integerPart));
}
/**
* Sets the {@link #ARG_INTEGER_PART} argument.
* @param integerPart A non-empty string of digits with an optional
* leading + or -.
* @return This instance.
*/
public FractionBuilder setIntegerPart(String integerPart) {
return setStringArgument(TtsSpan.ARG_INTEGER_PART, integerPart);
}
/**
* Convenience method that converts the numerator to a String and sets
* the argument {@link #ARG_NUMERATOR}.
* @param numerator The numerator.
* @return This instance.
*/
public FractionBuilder setNumerator(long numerator) {
return setNumerator(String.valueOf(numerator));
}
/**
* Sets the {@link #ARG_NUMERATOR} argument.
* @param numerator A non-empty string of digits with an optional
* leading + or -.
* @return This instance.
*/
public FractionBuilder setNumerator(String numerator) {
return setStringArgument(TtsSpan.ARG_NUMERATOR, numerator);
}
/**
* Convenience method that converts the denominator to a String and sets
* the argument {@link #ARG_DENOMINATOR}.
* @param denominator The denominator.
* @return This instance.
*/
public FractionBuilder setDenominator(long denominator) {
return setDenominator(String.valueOf(denominator));
}
/**
* Sets the {@link #ARG_DENOMINATOR} argument.
* @param denominator A non-empty string of digits with an optional
* leading + or -.
* @return This instance.
*/
public FractionBuilder setDenominator(String denominator) {
return setStringArgument(TtsSpan.ARG_DENOMINATOR, denominator);
}
}
/**
* A builder for TtsSpans of type {@link #TYPE_MEASURE}.
*/
public static class MeasureBuilder
extends SemioticClassBuilder<MeasureBuilder> {
/**
* Creates a builder for a TtsSpan of type {@link #TYPE_MEASURE}.
*/
public MeasureBuilder() {
super(TtsSpan.TYPE_MEASURE);
}
/**
* Convenience method that converts the number to a String and set it to
* the value for {@link #ARG_NUMBER}.
* @param number The amount of the measure.
* @return This instance.
*/
public MeasureBuilder setNumber(long number) {
return setNumber(String.valueOf(number));
}
/**
* Sets the {@link #ARG_NUMBER} argument.
* @param number A non-empty string of digits with an optional
* leading + or -.
* @return This instance.
*/
public MeasureBuilder setNumber(String number) {
return setStringArgument(TtsSpan.ARG_NUMBER, number);
}
/**
* Convenience method that converts the integer part to a String and set
* it to the value for {@link #ARG_INTEGER_PART}.
* @param integerPart The integer part of a decimal or fraction.
* @return This instance.
*/
public MeasureBuilder setIntegerPart(long integerPart) {
return setNumber(String.valueOf(integerPart));
}
/**
* Sets the {@link #ARG_INTEGER_PART} argument.
* @param integerPart The integer part of a decimal or fraction; a
* non-empty string of digits with an optional
* leading + or -.
* @return This instance.
*/
public MeasureBuilder setIntegerPart(String integerPart) {
return setStringArgument(TtsSpan.ARG_INTEGER_PART, integerPart);
}
/**
* Sets the {@link #ARG_FRACTIONAL_PART} argument.
* @param fractionalPart The fractional part of a decimal; a non-empty
* string of digits with an optional leading + or -.
* @return This instance.
*/
public MeasureBuilder setFractionalPart(String fractionalPart) {
return setStringArgument(TtsSpan.ARG_FRACTIONAL_PART,
fractionalPart);
}
/**
* Convenience method that converts the numerator to a String and set it
* to the value for {@link #ARG_NUMERATOR}.
* @param numerator The numerator of a fraction.
* @return This instance.
*/
public MeasureBuilder setNumerator(long numerator) {
return setNumerator(String.valueOf(numerator));
}
/**
* Sets the {@link #ARG_NUMERATOR} argument.
* @param numerator The numerator of a fraction; a non-empty string of
* digits with an optional leading + or -.
* @return This instance.
*/
public MeasureBuilder setNumerator(String numerator) {
return setStringArgument(TtsSpan.ARG_NUMERATOR, numerator);
}
/**
* Convenience method that converts the denominator to a String and set
* it to the value for {@link #ARG_DENOMINATOR}.
* @param denominator The denominator of a fraction.
* @return This instance.
*/
public MeasureBuilder setDenominator(long denominator) {
return setDenominator(String.valueOf(denominator));
}
/**
* Sets the {@link #ARG_DENOMINATOR} argument.
* @param denominator The denominator of a fraction; a non-empty string
* of digits with an optional leading + or -.
* @return This instance.
*/
public MeasureBuilder setDenominator(String denominator) {
return setStringArgument(TtsSpan.ARG_DENOMINATOR, denominator);
}
/**
* Sets the {@link #ARG_UNIT} argument.
* @param unit The unit of the measure.
* @return This instance.
* @see {@link TtsSpan.ARG_UNIT}
*/
public MeasureBuilder setUnit(String unit) {
return setStringArgument(TtsSpan.ARG_UNIT, unit);
}
}
/**
* A builder for TtsSpans of type {@link #TYPE_TIME}.
*/
public static class TimeBuilder
extends SemioticClassBuilder<TimeBuilder> {
/**
* Creates a builder for a TtsSpan of type {@link #TYPE_TIME}.
*/
public TimeBuilder() {
super(TtsSpan.TYPE_TIME);
}
/**
* Creates a builder for a TtsSpan of type {@link #TYPE_TIME} and
* sets the {@link #ARG_HOURS} and {@link #ARG_MINUTES} arguments.
*/
public TimeBuilder(int hours, int minutes) {
this();
setHours(hours);
setMinutes(minutes);
}
/**
* Sets the {@link #ARG_HOURS} argument.
* @param hours The value to be set for hours. See {@link #ARG_HOURS}.
* @return This instance.
* @see {@link #ARG_HOURS}
*/
public TimeBuilder setHours(int hours) {
return setIntArgument(TtsSpan.ARG_HOURS, hours);
}
/**
* Sets the {@link #ARG_MINUTES} argument.
* @param minutes The value to be set for minutes. See
* {@link #ARG_MINUTES}.
* @return This instance.
* @see {@link #ARG_MINUTES}
*/
public TimeBuilder setMinutes(int minutes) {
return setIntArgument(TtsSpan.ARG_MINUTES, minutes);
}
}
/**
* A builder for TtsSpans of type {@link #TYPE_DATE}.
*/
public static class DateBuilder
extends SemioticClassBuilder<DateBuilder> {
/**
* Creates a builder for a TtsSpan of type {@link #TYPE_DATE}.
*/
public DateBuilder() {
super(TtsSpan.TYPE_DATE);
}
/**
* Creates a builder for a TtsSpan of type {@link #TYPE_TIME} and
* possibly sets the {@link #ARG_WEEKDAY}, {@link #ARG_DAY},
* {@link #ARG_MONTH} and {@link #ARG_YEAR} arguments. Pass null to any
* argument to leave it unset.
*/
public DateBuilder(Integer weekday,
Integer day,
Integer month,
Integer year) {
this();
if (weekday != null) {
setWeekday(weekday);
}
if (day != null) {
setDay(day);
}
if (month != null) {
setMonth(month);
}
if (year != null) {
setYear(year);
}
}
/**
* Sets the {@link #ARG_WEEKDAY} argument.
* @param weekday The value to be set for weekday. See
* {@link #ARG_WEEKDAY}.
* @return This instance.
* @see {@link #ARG_WEEKDAY}
*/
public DateBuilder setWeekday(int weekday) {
return setIntArgument(TtsSpan.ARG_WEEKDAY, weekday);
}
/**
* Sets the {@link #ARG_DAY} argument.
* @param day The value to be set for day. See {@link #ARG_DAY}.
* @return This instance.
* @see {@link #ARG_DAY}
*/
public DateBuilder setDay(int day) {
return setIntArgument(TtsSpan.ARG_DAY, day);
}
/**
* Sets the {@link #ARG_MONTH} argument.
* @param month The value to be set for month. See {@link #ARG_MONTH}.
* @return This instance.
* @see {@link #ARG_MONTH}
*/
public DateBuilder setMonth(int month) {
return setIntArgument(TtsSpan.ARG_MONTH, month);
}
/**
* Sets the {@link #ARG_YEAR} argument.
* @param year The value to be set for year. See {@link #ARG_YEAR}.
* @return This instance.
* @see {@link #ARG_YEAR}
*/
public DateBuilder setYear(int year) {
return setIntArgument(TtsSpan.ARG_YEAR, year);
}
}
/**
* A builder for TtsSpans of type {@link #TYPE_MONEY}.
*/
public static class MoneyBuilder
extends SemioticClassBuilder<MoneyBuilder> {
/**
* Creates a TtsSpan of type {@link #TYPE_MONEY}.
*/
public MoneyBuilder() {
super(TtsSpan.TYPE_MONEY);
}
/**
* Convenience method that converts the number to a String and set it to
* the value for {@link #ARG_INTEGER_PART}.
* @param integerPart The integer part of the amount.
* @return This instance.
*/
public MoneyBuilder setIntegerPart(long integerPart) {
return setIntegerPart(String.valueOf(integerPart));
}
/**
* Sets the {@link #ARG_INTEGER_PART} argument.
* @param integerPart A non-empty string of digits with an optional
* leading + or -.
* @return This instance.
*/
public MoneyBuilder setIntegerPart(String integerPart) {
return setStringArgument(TtsSpan.ARG_INTEGER_PART, integerPart);
}
/**
* Sets the {@link #ARG_FRACTIONAL_PART} argument.
* @param fractionalPart Can be a string of digits of any size.
* @return This instance.
*/
public MoneyBuilder setFractionalPart(String fractionalPart) {
return setStringArgument(TtsSpan.ARG_FRACTIONAL_PART, fractionalPart);
}
/**
* Sets the {@link #ARG_CURRENCY} argument.
* @param currency Should be a ISO4217 currency code, e.g. "USD".
* @return This instance.
*/
public MoneyBuilder setCurrency(String currency) {
return setStringArgument(TtsSpan.ARG_CURRENCY, currency);
}
/**
* Sets the {@link #ARG_QUANTITY} argument.
* @param quantity
* @return This instance.
*/
public MoneyBuilder setQuantity(String quantity) {
return setStringArgument(TtsSpan.ARG_QUANTITY, quantity);
}
}
/**
* A builder for TtsSpans of type {@link #TYPE_TELEPHONE}.
*/
public static class TelephoneBuilder
extends SemioticClassBuilder<TelephoneBuilder> {
/**
* Creates a TtsSpan of type {@link #TYPE_TELEPHONE}.
*/
public TelephoneBuilder() {
super(TtsSpan.TYPE_TELEPHONE);
}
/**
* Creates a TtsSpan of type {@link #TYPE_TELEPHONE} and sets the
* {@link #ARG_NUMBER_PARTS} argument.
*/
public TelephoneBuilder(String numberParts) {
this();
setNumberParts(numberParts);
}
/**
* Sets the {@link #ARG_COUNTRY_CODE} argument.
* @param countryCode The country code can be a series of digits
* optionally prefixed with a "+".
* @return This instance.
*/
public TelephoneBuilder setCountryCode(String countryCode) {
return setStringArgument(TtsSpan.ARG_COUNTRY_CODE, countryCode);
}
/**
* Sets the {@link #ARG_NUMBER_PARTS} argument.
* @param numberParts The main telephone number. Can be a series of
* digits and letters separated by spaces, "/", "-" or ".".
* @return This instance.
*/
public TelephoneBuilder setNumberParts(String numberParts) {
return setStringArgument(TtsSpan.ARG_NUMBER_PARTS, numberParts);
}
/**
* Sets the {@link #ARG_EXTENSION} argument.
* @param extension The extension can be a series of digits.
* @return This instance.
*/
public TelephoneBuilder setExtension(String extension) {
return setStringArgument(TtsSpan.ARG_EXTENSION, extension);
}
}
/**
* A builder for TtsSpans of type {@link #TYPE_ELECTRONIC}.
*/
public static class ElectronicBuilder
extends SemioticClassBuilder<ElectronicBuilder> {
/**
* Creates a TtsSpan of type {@link #TYPE_ELECTRONIC}.
*/
public ElectronicBuilder() {
super(TtsSpan.TYPE_ELECTRONIC);
}
/**
* Sets the {@link #ARG_USERNAME} and {@link #ARG_DOMAIN}
* arguments, representing an email address.
* @param username The part before the @ in the email address.
* @param domain The part after the @ in the email address.
* @return This instance.
*/
public ElectronicBuilder setEmailArguments(String username,
String domain) {
return setDomain(domain).setUsername(username);
}
/**
* Sets the {@link #ARG_PROTOCOL} argument.
* @param protocol The protocol of the URI. Examples are "http" and
* "ftp".
* @return This instance.
*/
public ElectronicBuilder setProtocol(String protocol) {
return setStringArgument(TtsSpan.ARG_PROTOCOL, protocol);
}
/**
* Sets the {@link #ARG_USERNAME} argument.
* @return This instance.
*/
public ElectronicBuilder setUsername(String username) {
return setStringArgument(TtsSpan.ARG_USERNAME, username);
}
/**
* Sets the {@link #ARG_PASSWORD} argument.
* @return This instance.
*/
public ElectronicBuilder setPassword(String password) {
return setStringArgument(TtsSpan.ARG_PASSWORD, password);
}
/**
* Sets the {@link #ARG_DOMAIN} argument.
* @param domain The domain, for example "source.android.com".
* @return This instance.
*/
public ElectronicBuilder setDomain(String domain) {
return setStringArgument(TtsSpan.ARG_DOMAIN, domain);
}
/**
* Sets the {@link #ARG_PORT} argument.
* @return This instance.
*/
public ElectronicBuilder setPort(int port) {
return setIntArgument(TtsSpan.ARG_PORT, port);
}
/**
* Sets the {@link #ARG_PATH} argument.
* @param path For example "source/index.html".
* @return This instance.
*/
public ElectronicBuilder setPath(String path) {
return setStringArgument(TtsSpan.ARG_PATH, path);
}
/**
* Sets the {@link #ARG_QUERY_STRING} argument.
* @param queryString For example "arg=value&argtwo=value".
* @return This instance.
*/
public ElectronicBuilder setQueryString(String queryString) {
return setStringArgument(TtsSpan.ARG_QUERY_STRING, queryString);
}
/**
* Sets the {@link #ARG_FRAGMENT_ID} argument.
* @return This instance.
*/
public ElectronicBuilder setFragmentId(String fragmentId) {
return setStringArgument(TtsSpan.ARG_FRAGMENT_ID, fragmentId);
}
}
/**
* A builder for TtsSpans of type {@link #TYPE_DIGITS}.
*/
public static class DigitsBuilder
extends SemioticClassBuilder<DigitsBuilder> {
/**
* Creates a builder for a TtsSpan of type {@link #TYPE_DIGITS}.
*/
public DigitsBuilder() {
super(TtsSpan.TYPE_DIGITS);
}
/**
* Creates a builder for a TtsSpan of type {@link #TYPE_DIGITS}
* and sets the {@link #ARG_DIGITS} argument.
*/
public DigitsBuilder(String digits) {
this();
setDigits(digits);
}
/**
* Sets the {@link #ARG_DIGITS} argument.
* @param digits A string of digits.
* @return This instance.
*/
public DigitsBuilder setDigits(String digits) {
return setStringArgument(TtsSpan.ARG_DIGITS, digits);
}
}
/**
* A builder for TtsSpans of type {@link #TYPE_VERBATIM}.
*/
public static class VerbatimBuilder
extends SemioticClassBuilder<VerbatimBuilder> {
/**
* Creates a builder for a TtsSpan of type {@link #TYPE_VERBATIM}.
*/
public VerbatimBuilder() {
super(TtsSpan.TYPE_VERBATIM);
}
/**
* Creates a builder for a TtsSpan of type {@link #TYPE_VERBATIM}
* and sets the {@link #ARG_VERBATIM} argument.
*/
public VerbatimBuilder(String verbatim) {
this();
setVerbatim(verbatim);
}
/**
* Sets the {@link #ARG_VERBATIM} argument.
* @param verbatim A string of characters that will be read verbatim,
* except whitespace.
* @return This instance.
*/
public VerbatimBuilder setVerbatim(String verbatim) {
return setStringArgument(TtsSpan.ARG_VERBATIM, verbatim);
}
}
}