content: /*
   * 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 android.os.Parcel;
  import android.os.PersistableBundle;
  import android.text.ParcelableSpan;
  import android.text.TextUtils;
  
  import java.text.NumberFormat;
  import java.util.Locale;
  
  /**
   * 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 #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 setIntegerPart(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 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 #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 #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 #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 #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 #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 #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);
          }
      }
  }
  