• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2014 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.text.style;
18 
19 import static com.android.text.flags.Flags.FLAG_TTS_SPAN_DURATION;
20 
21 import android.annotation.FlaggedApi;
22 import android.annotation.IntRange;
23 import android.annotation.NonNull;
24 import android.os.Parcel;
25 import android.os.PersistableBundle;
26 import android.text.ParcelableSpan;
27 import android.text.TextUtils;
28 
29 import java.text.NumberFormat;
30 import java.util.Locale;
31 
32 /**
33  * A span that supplies additional meta-data for the associated text intended
34  * for text-to-speech engines. If the text is being processed by a
35  * text-to-speech engine, the engine may use the data in this span in addition
36  * to or instead of its associated text.
37  *
38  * Each instance of a TtsSpan has a type, for example {@link #TYPE_DATE}
39  * or {@link #TYPE_MEASURE}. And a list of arguments, provided as
40  * key-value pairs in a bundle.
41  *
42  * The inner classes are there for convenience and provide builders for each
43  * TtsSpan type.
44  */
45 @android.ravenwood.annotation.RavenwoodKeepWholeClass
46 public class TtsSpan implements ParcelableSpan {
47     private final String mType;
48     private final PersistableBundle mArgs;
49 
50     /**
51      * This span type can be used to add morphosyntactic features to the text it
52      * spans over, or synthesize a something else than the spanned text. Use
53      * the argument {@link #ARG_TEXT} to set a different text.
54      * Accepts the arguments {@link #ARG_GENDER},
55      * {@link #ARG_ANIMACY}, {@link #ARG_MULTIPLICITY} and
56      * {@link #ARG_CASE}.
57      */
58     public static final String TYPE_TEXT = "android.type.text";
59 
60     /**
61      * The text associated with this span is a cardinal. Must include the
62      * number to be synthesized with {@link #ARG_NUMBER}.
63      * Also accepts the arguments {@link #ARG_GENDER},
64      * {@link #ARG_ANIMACY}, {@link #ARG_MULTIPLICITY} and
65      * {@link #ARG_CASE}.
66      */
67     public static final String TYPE_CARDINAL = "android.type.cardinal";
68 
69     /**
70      * The text associated with this span is an ordinal. Must include the
71      * number to be synthesized with {@link #ARG_NUMBER}.
72      * Also accepts the arguments {@link #ARG_GENDER},
73      * {@link #ARG_ANIMACY}, {@link #ARG_MULTIPLICITY} and
74      * {@link #ARG_CASE}.
75      */
76     public static final String TYPE_ORDINAL = "android.type.ordinal";
77 
78     /**
79      * The text associated with this span is a decimal number. Must include the
80      * number to be synthesized with {@link #ARG_INTEGER_PART} and
81      * {@link #ARG_FRACTIONAL_PART}.
82      * Also accepts the arguments {@link #ARG_GENDER},
83      * {@link #ARG_ANIMACY}, {@link #ARG_MULTIPLICITY} and
84      * {@link #ARG_CASE}.
85      */
86     public static final String TYPE_DECIMAL = "android.type.decimal";
87 
88     /**
89      * The text associated with this span is a fractional number. Must include
90      * the number to be synthesized with {@link #ARG_NUMERATOR} and
91      * {@link #ARG_DENOMINATOR}. {@link #ARG_INTEGER_PART} is optional
92      * Also accepts the arguments {@link #ARG_GENDER},
93      * {@link #ARG_ANIMACY}, {@link #ARG_MULTIPLICITY} and
94      * {@link #ARG_CASE}.
95      */
96     public static final String TYPE_FRACTION = "android.type.fraction";
97 
98     /**
99      * The text associated with this span is a measure, consisting of a number
100      * and a unit. The number can be a cardinal, decimal or a fraction. Set the
101      * number with the same arguments as {@link #TYPE_CARDINAL},
102      * {@link #TYPE_DECIMAL} or {@link #TYPE_FRACTION}. The unit can be
103      * specified with {@link #ARG_UNIT}.
104      * Also accepts the arguments {@link #ARG_GENDER},
105      * {@link #ARG_ANIMACY}, {@link #ARG_MULTIPLICITY} and
106      * {@link #ARG_CASE}.
107      */
108     public static final String TYPE_MEASURE = "android.type.measure";
109 
110     /**
111      * The text associated with this span is a time, consisting of a number of
112      * hours, minutes, and seconds specified with {@link #ARG_HOURS}, {@link #ARG_MINUTES}, and
113      * {@link #ARG_SECONDS}.
114      * Also accepts the arguments {@link #ARG_GENDER},
115      * {@link #ARG_ANIMACY}, {@link #ARG_MULTIPLICITY} and
116      * {@link #ARG_CASE}. This is different from {@link #TYPE_DURATION}. This should be used to
117      * convey a particular moment in time, such as a clock time, while {@link #TYPE_DURATION} should
118      * be used to convey an interval of time.
119      */
120     public static final String TYPE_TIME = "android.type.time";
121 
122     /**
123      * The text associated with this span is a duration, consisting of a number of
124      * hours, minutes, and seconds specified with {@link #ARG_HOURS},
125      * {@link #ARG_MINUTES}, and {@link #ARG_SECONDS}. This is different from {@link #TYPE_TIME}.
126      * This should be used to convey an interval of time, while {@link #TYPE_TIME} should be used to
127      * convey a particular moment in time, such as a clock time.
128      */
129     @FlaggedApi(FLAG_TTS_SPAN_DURATION)
130     public static final String TYPE_DURATION = "android.type.duration";
131 
132     /**
133      * The text associated with this span is a date. At least one of the
134      * arguments {@link #ARG_MONTH} and {@link #ARG_YEAR} has to be provided.
135      * The argument {@link #ARG_DAY} is optional if {@link #ARG_MONTH} is set.
136      * The argument {@link #ARG_WEEKDAY} is optional if {@link #ARG_DAY} is set.
137      * Also accepts the arguments {@link #ARG_GENDER}, {@link #ARG_ANIMACY},
138      * {@link #ARG_MULTIPLICITY} and {@link #ARG_CASE}.
139      */
140     public static final String TYPE_DATE = "android.type.date";
141 
142     /**
143      * The text associated with this span is a telephone number. The argument
144      * {@link #ARG_NUMBER_PARTS} is required. {@link #ARG_COUNTRY_CODE} and
145      * {@link #ARG_EXTENSION} are optional.
146      * Also accepts the arguments {@link #ARG_GENDER}, {@link #ARG_ANIMACY},
147      * {@link #ARG_MULTIPLICITY} and {@link #ARG_CASE}.
148      */
149     public static final String TYPE_TELEPHONE = "android.type.telephone";
150 
151     /**
152      * The text associated with this span is a URI (can be used for URLs and
153      * email addresses). The full schema for URLs, which email addresses can
154      * effectively be seen as a subset of, is:
155      * protocol://username:password@domain:port/path?query_string#fragment_id
156      * Hence populating just username and domain will read as an email address.
157      * All arguments are optional, but at least one has to be provided:
158      * {@link #ARG_PROTOCOL}, {@link #ARG_USERNAME}, {@link #ARG_PASSWORD},
159      * {@link #ARG_DOMAIN}, {@link #ARG_PORT}, {@link #ARG_PATH},
160      * {@link #ARG_QUERY_STRING} and {@link #ARG_FRAGMENT_ID}.
161      * Also accepts the arguments {@link #ARG_GENDER}, {@link #ARG_ANIMACY},
162      * {@link #ARG_MULTIPLICITY} and {@link #ARG_CASE}.
163      */
164     public static final String TYPE_ELECTRONIC = "android.type.electronic";
165 
166     /**
167      * The text associated with this span is an amount of money. Set the amount
168      * with the same arguments as {@link #TYPE_DECIMAL}.
169      * {@link #ARG_CURRENCY} is used to set the currency. {@link #ARG_QUANTITY}
170      * is optional.
171      * Also accepts the arguments {@link #ARG_GENDER}, {@link #ARG_ANIMACY},
172      * {@link #ARG_MULTIPLICITY} and {@link #ARG_CASE}.
173      */
174     public static final String TYPE_MONEY = "android.type.money";
175 
176     /**
177      * The text associated with this span is a series of digits that have to be
178      * read sequentially. The digits can be set with {@link #ARG_DIGITS}.
179      * Also accepts the arguments {@link #ARG_GENDER}, {@link #ARG_ANIMACY},
180      * {@link #ARG_MULTIPLICITY} and {@link #ARG_CASE}.
181      */
182     public static final String TYPE_DIGITS = "android.type.digits";
183 
184     /**
185      * The text associated with this span is a series of characters that have to
186      * be read verbatim. The engine will attempt to read out any character like
187      * punctuation but excluding whitespace. {@link #ARG_VERBATIM} is required.
188      * Also accepts the arguments {@link #ARG_GENDER},
189      * {@link #ARG_ANIMACY}, {@link #ARG_MULTIPLICITY} and {@link #ARG_CASE}.
190      */
191     public static final String TYPE_VERBATIM = "android.type.verbatim";
192 
193     /**
194      * String argument supplying gender information. Can be any of
195      * {@link #GENDER_NEUTRAL}, {@link #GENDER_MALE} and
196      * {@link #GENDER_FEMALE}.
197      */
198     public static final String ARG_GENDER = "android.arg.gender";
199 
200     public static final String GENDER_NEUTRAL = "android.neutral";
201     public static final String GENDER_MALE = "android.male";
202     public static final String GENDER_FEMALE = "android.female";
203 
204     /**
205      * String argument supplying animacy information. Can be
206      * {@link #ANIMACY_ANIMATE} or
207      * {@link #ANIMACY_INANIMATE}
208      */
209     public static final String ARG_ANIMACY = "android.arg.animacy";
210 
211     public static final String ANIMACY_ANIMATE = "android.animate";
212     public static final String ANIMACY_INANIMATE = "android.inanimate";
213 
214     /**
215      * String argument supplying multiplicity information. Can be any of
216      * {@link #MULTIPLICITY_SINGLE}, {@link #MULTIPLICITY_DUAL} and
217      * {@link #MULTIPLICITY_PLURAL}
218      */
219     public static final String ARG_MULTIPLICITY = "android.arg.multiplicity";
220 
221     public static final String MULTIPLICITY_SINGLE = "android.single";
222     public static final String MULTIPLICITY_DUAL = "android.dual";
223     public static final String MULTIPLICITY_PLURAL = "android.plural";
224 
225     /**
226      * String argument supplying case information. Can be any of
227      * {@link #CASE_NOMINATIVE}, {@link #CASE_ACCUSATIVE}, {@link #CASE_DATIVE},
228      * {@link #CASE_ABLATIVE}, {@link #CASE_GENITIVE}, {@link #CASE_VOCATIVE},
229      * {@link #CASE_LOCATIVE} and {@link #CASE_INSTRUMENTAL}
230      */
231     public static final String ARG_CASE = "android.arg.case";
232 
233     public static final String CASE_NOMINATIVE = "android.nominative";
234     public static final String CASE_ACCUSATIVE = "android.accusative";
235     public static final String CASE_DATIVE = "android.dative";
236     public static final String CASE_ABLATIVE = "android.ablative";
237     public static final String CASE_GENITIVE = "android.genitive";
238     public static final String CASE_VOCATIVE = "android.vocative";
239     public static final String CASE_LOCATIVE = "android.locative";
240     public static final String CASE_INSTRUMENTAL = "android.instrumental";
241 
242     /**
243      * String supplying the text to be synthesized. The synthesizer is free
244      * to decide how to interpret the text.
245      * Can be used with {@link #TYPE_TEXT}.
246      */
247     public static final String ARG_TEXT = "android.arg.text";
248 
249     /**
250      * Argument used to specify a whole number. The value can be a string of
251      * digits of any size optionally prefixed with a - or +.
252      * Can be used with {@link #TYPE_CARDINAL} and {@link #TYPE_ORDINAL}.
253      */
254     public static final String ARG_NUMBER = "android.arg.number";
255 
256     /**
257      * Argument used to specify the integer part of a decimal or fraction. The
258      * value can be a string of digits of any size optionally prefixed with
259      * a - or +.
260      * Can be used with {@link #TYPE_DECIMAL} and {@link #TYPE_FRACTION}.
261      */
262     public static final String ARG_INTEGER_PART = "android.arg.integer_part";
263 
264     /**
265      * Argument used to specify the fractional part of a decimal. The value can
266      * be a string of digits of any size.
267      * Can be used with {@link #TYPE_DECIMAL}.
268      */
269     public static final String ARG_FRACTIONAL_PART =
270         "android.arg.fractional_part";
271 
272     /**
273      * Argument used to choose the suffix (thousand, million, etc) that is used
274      * to pronounce large amounts of money. For example it can be used to
275      * disambiguate between "two thousand five hundred dollars" and
276      * "two point five thousand dollars".
277      * If implemented, engines should support at least "1000", "1000000",
278      * "1000000000" and "1000000000000".
279      * Example: if the {@link #ARG_INTEGER_PART} argument is "10", the
280      * {@link #ARG_FRACTIONAL_PART} argument is "4", the {@link #ARG_QUANTITY}
281      * argument is "1000" and the {@link #ARG_CURRENCY} argument is "usd", the
282      * TTS engine may pronounce the span as "ten point four thousand dollars".
283      * With the same example but with the quantity set as "1000000" the TTS
284      * engine may pronounce the span as "ten point four million dollars".
285      * Can be used with {@link #TYPE_MONEY}.
286      */
287     public static final String ARG_QUANTITY =
288             "android.arg.quantity";
289 
290     /**
291      * Argument used to specify the numerator of a fraction. The value can be a
292      * string of digits of any size optionally prefixed with a - or +.
293      * Can be used with {@link #TYPE_FRACTION}.
294      */
295     public static final String ARG_NUMERATOR = "android.arg.numerator";
296 
297     /**
298      * Argument used to specify the denominator of a fraction. The value can be
299      * a string of digits of any size optionally prefixed with a + or -.
300      * Can be used with {@link #TYPE_FRACTION}.
301      */
302     public static final String ARG_DENOMINATOR = "android.arg.denominator";
303 
304     /**
305      * Argument used to specify the unit of a measure. The unit should always be
306      * specified in English singular form. Prefixes may be used. Engines will do
307      * their best to pronounce them correctly in the language used. Engines are
308      * expected to at least support the most common ones like "meter", "second",
309      * "degree celsius" and "degree fahrenheit" with some common prefixes like
310      * "milli" and "kilo".
311      * Can be used with {@link #TYPE_MEASURE}.
312      */
313     public static final String ARG_UNIT = "android.arg.unit";
314 
315     /**
316      * Argument used to specify the hours of a time or duration. The hours should be
317      * provided as an integer in the range from 0 up to and including 24 for
318      * {@link #TYPE_TIME}.
319      * Can be used with {@link #TYPE_TIME} or {@link #TYPE_DURATION}.
320      */
321     public static final String ARG_HOURS = "android.arg.hours";
322 
323     /**
324      * Argument used to specify the minutes of a time or duration. The minutes should be
325      * provided as an integer in the range from 0 up to and including 59 for
326      * {@link #TYPE_TIME}.
327      * Can be used with {@link #TYPE_TIME} or {@link #TYPE_DURATION}.
328      */
329     public static final String ARG_MINUTES = "android.arg.minutes";
330 
331     /**
332      * Argument used to specify the seconds of a time or duration. The seconds should be
333      * provided as an integer in the range from 0 up to and including 59 for
334      * {@link #TYPE_TIME}.
335      * Can be used with {@link #TYPE_TIME} or {@link #TYPE_DURATION}.
336      */
337     @FlaggedApi(FLAG_TTS_SPAN_DURATION)
338     public static final String ARG_SECONDS = "android.arg.seconds";
339 
340     /**
341      * Argument used to specify the weekday of a date. The value should be
342      * provided as an integer and can be any of {@link #WEEKDAY_SUNDAY},
343      * {@link #WEEKDAY_MONDAY}, {@link #WEEKDAY_TUESDAY},
344      * {@link #WEEKDAY_WEDNESDAY}, {@link #WEEKDAY_THURSDAY},
345      * {@link #WEEKDAY_FRIDAY} and {@link #WEEKDAY_SATURDAY}.
346      * Can be used with {@link #TYPE_DATE}.
347      */
348     public static final String ARG_WEEKDAY = "android.arg.weekday";
349 
350     public static final int WEEKDAY_SUNDAY = 1;
351     public static final int WEEKDAY_MONDAY = 2;
352     public static final int WEEKDAY_TUESDAY = 3;
353     public static final int WEEKDAY_WEDNESDAY = 4;
354     public static final int WEEKDAY_THURSDAY = 5;
355     public static final int WEEKDAY_FRIDAY = 6;
356     public static final int WEEKDAY_SATURDAY = 7;
357 
358     /**
359      * Argument used to specify the day of the month of a date. The value should
360      * be provided as an integer in the range from 1 up to and including 31.
361      * Can be used with {@link #TYPE_DATE}.
362      */
363     public static final String ARG_DAY = "android.arg.day";
364 
365     /**
366      * Argument used to specify the month of a date. The value should be
367      * provided as an integer and can be any of {@link #MONTH_JANUARY},
368      * {@link #MONTH_FEBRUARY},  {@link #MONTH_MARCH}, {@link #MONTH_APRIL},
369      * {@link #MONTH_MAY}, {@link #MONTH_JUNE}, {@link #MONTH_JULY},
370      * {@link #MONTH_AUGUST}, {@link #MONTH_SEPTEMBER}, {@link #MONTH_OCTOBER},
371      * {@link #MONTH_NOVEMBER} and {@link #MONTH_DECEMBER}.
372      * Can be used with {@link #TYPE_DATE}.
373      */
374     public static final String ARG_MONTH = "android.arg.month";
375 
376     public static final int MONTH_JANUARY = 0;
377     public static final int MONTH_FEBRUARY = 1;
378     public static final int MONTH_MARCH = 2;
379     public static final int MONTH_APRIL = 3;
380     public static final int MONTH_MAY = 4;
381     public static final int MONTH_JUNE = 5;
382     public static final int MONTH_JULY = 6;
383     public static final int MONTH_AUGUST = 7;
384     public static final int MONTH_SEPTEMBER = 8;
385     public static final int MONTH_OCTOBER = 9;
386     public static final int MONTH_NOVEMBER = 10;
387     public static final int MONTH_DECEMBER = 11;
388 
389     /**
390      * Argument used to specify the year of a date. The value should be provided
391      * as a positive integer.
392      * Can be used with {@link #TYPE_DATE}.
393      */
394     public static final String ARG_YEAR = "android.arg.year";
395 
396     /**
397      * Argument used to specify the country code of a telephone number. Can be
398      * a string of digits optionally prefixed with a "+".
399      * Can be used with {@link #TYPE_TELEPHONE}.
400      */
401     public static final String ARG_COUNTRY_CODE = "android.arg.country_code";
402 
403     /**
404      * Argument used to specify the main number part of a telephone number. Can
405      * be a string of digits where the different parts of the telephone number
406      * can be separated with a space, '-', '/' or '.'.
407      * Can be used with {@link #TYPE_TELEPHONE}.
408      */
409     public static final String ARG_NUMBER_PARTS = "android.arg.number_parts";
410 
411     /**
412      * Argument used to specify the extension part of a telephone number. Can be
413      * a string of digits.
414      * Can be used with {@link #TYPE_TELEPHONE}.
415      */
416     public static final String ARG_EXTENSION = "android.arg.extension";
417 
418     /**
419      * Argument used to specify the protocol of a URI. Examples are "http" and
420      * "ftp".
421      * Can be used with {@link #TYPE_ELECTRONIC}.
422      */
423     public static final String ARG_PROTOCOL = "android.arg.protocol";
424 
425     /**
426      * Argument used to specify the username part of a URI. Should be set as a
427      * string.
428      * Can be used with {@link #TYPE_ELECTRONIC}.
429      */
430     public static final String ARG_USERNAME = "android.arg.username";
431 
432     /**
433      * Argument used to specify the password part of a URI. Should be set as a
434      * string.
435      * Can be used with {@link #TYPE_ELECTRONIC}.
436      */
437     public static final String ARG_PASSWORD = "android.arg.password";
438 
439     /**
440      * Argument used to specify the domain part of a URI. For example
441      * "source.android.com".
442      * Can be used with {@link #TYPE_ELECTRONIC}.
443      */
444     public static final String ARG_DOMAIN = "android.arg.domain";
445 
446     /**
447      * Argument used to specify the port number of a URI. Should be specified as
448      * an integer.
449      * Can be used with {@link #TYPE_ELECTRONIC}.
450      */
451     public static final String ARG_PORT = "android.arg.port";
452 
453     /**
454      * Argument used to specify the path part of a URI. For example
455      * "source/index.html".
456      * Can be used with {@link #TYPE_ELECTRONIC}.
457      */
458     public static final String ARG_PATH = "android.arg.path";
459 
460     /**
461      * Argument used to specify the query string of a URI. For example
462      * "arg=value&argtwo=value".
463      * Can be used with {@link #TYPE_ELECTRONIC}.
464      */
465     public static final String ARG_QUERY_STRING = "android.arg.query_string";
466 
467     /**
468      * Argument used to specify the fragment id of a URI. Should be specified as
469      * a string.
470      * Can be used with {@link #TYPE_ELECTRONIC}.
471      */
472     public static final String ARG_FRAGMENT_ID = "android.arg.fragment_id";
473 
474     /**
475      * Argument used to specify the currency. Should be a ISO4217 currency code,
476      * e.g. "USD".
477      * Can be used with {@link #TYPE_MONEY}.
478      */
479     public static final String ARG_CURRENCY = "android.arg.money";
480 
481     /**
482      * Argument used to specify a string of digits.
483      * Can be used with {@link #TYPE_DIGITS}.
484      */
485     public static final String ARG_DIGITS = "android.arg.digits";
486 
487     /**
488      * Argument used to specify a string where the characters are read verbatim,
489      * except whitespace.
490      * Can be used with {@link #TYPE_VERBATIM}.
491      */
492     public static final String ARG_VERBATIM = "android.arg.verbatim";
493 
TtsSpan(String type, PersistableBundle args)494     public TtsSpan(String type, PersistableBundle args) {
495         mType = type;
496         mArgs = args;
497     }
498 
TtsSpan(Parcel src)499     public TtsSpan(Parcel src) {
500         mType = src.readString();
501         mArgs = src.readPersistableBundle();
502     }
503 
504     /**
505      * Returns the type.
506      * @return The type of this instance.
507      */
getType()508     public String getType() {
509         return mType;
510     }
511 
512     /**
513      * Returns a bundle of the arguments set.
514      * @return The bundle of the arguments set.
515      */
getArgs()516     public PersistableBundle getArgs() {
517         return mArgs;
518     }
519 
520     @Override
describeContents()521     public int describeContents() {
522         return 0;
523     }
524 
525     @Override
writeToParcel(Parcel dest, int flags)526     public void writeToParcel(Parcel dest, int flags) {
527         writeToParcelInternal(dest, flags);
528     }
529 
530     /** @hide */
writeToParcelInternal(Parcel dest, int flags)531     public void writeToParcelInternal(Parcel dest, int flags) {
532         dest.writeString(mType);
533         dest.writePersistableBundle(mArgs);
534     }
535 
536     @Override
getSpanTypeId()537     public int getSpanTypeId() {
538         return getSpanTypeIdInternal();
539     }
540 
541     /** @hide */
getSpanTypeIdInternal()542     public int getSpanTypeIdInternal() {
543         return TextUtils.TTS_SPAN;
544     }
545 
546     /**
547      * A simple builder for TtsSpans.
548      * This builder can be used directly, but the more specific subclasses of
549      * this builder like {@link TtsSpan.TextBuilder} and
550      * {@link TtsSpan.CardinalBuilder} are likely more useful.
551      *
552      * This class uses generics so methods from this class can return instances
553      * of its child classes, resulting in a fluent API (CRTP pattern).
554      */
555     public static class Builder<C extends Builder<?>> {
556         // Holds the type of this class.
557         private final String mType;
558 
559         // Holds the arguments of this class. It only stores objects of type
560         // String, Integer and Long.
561         private PersistableBundle mArgs = new PersistableBundle();
562 
Builder(String type)563         public Builder(String type) {
564             mType = type;
565         }
566 
567         /**
568          * Returns a TtsSpan built from the parameters set by the setter
569          * methods.
570          * @return A TtsSpan built with parameters of this builder.
571          */
build()572         public TtsSpan build() {
573             return new TtsSpan(mType, mArgs);
574         }
575 
576         /**
577          * Sets an argument to a string value.
578          * @param arg The argument name.
579          * @param value The value the argument should be set to.
580          * @return This instance.
581          */
582         @SuppressWarnings("unchecked")
setStringArgument(String arg, String value)583         public C setStringArgument(String arg, String value) {
584             mArgs.putString(arg, value);
585             return (C) this;
586         }
587 
588         /**
589          * Sets an argument to an int value.
590          * @param arg The argument name.
591          * @param value The value the argument should be set to.
592          */
593         @SuppressWarnings("unchecked")
setIntArgument(String arg, int value)594         public C setIntArgument(String arg, int value) {
595             mArgs.putInt(arg, value);
596             return (C) this;
597         }
598 
599         /**
600          * Sets an argument to a long value.
601          * @param arg The argument name.
602          * @param value The value the argument should be set to.
603          */
604         @SuppressWarnings("unchecked")
setLongArgument(String arg, long value)605         public C setLongArgument(String arg, long value) {
606             mArgs.putLong(arg, value);
607             return (C) this;
608         }
609     }
610 
611     /**
612      * A builder for TtsSpans, has setters for morphosyntactic features.
613      * This builder can be used directly, but the more specific subclasses of
614      * this builder like {@link TtsSpan.TextBuilder} and
615      * {@link TtsSpan.CardinalBuilder} are likely more useful.
616      */
617     public static class SemioticClassBuilder<C extends SemioticClassBuilder<?>>
618             extends Builder<C> {
619 
SemioticClassBuilder(String type)620         public SemioticClassBuilder(String type) {
621             super(type);
622         }
623 
624         /**
625          * Sets the gender information for this instance.
626          * @param gender Can any of {@link #GENDER_NEUTRAL},
627          *     {@link #GENDER_MALE} and {@link #GENDER_FEMALE}.
628          * @return This instance.
629          */
setGender(String gender)630         public C setGender(String gender) {
631             return setStringArgument(TtsSpan.ARG_GENDER, gender);
632         }
633 
634         /**
635          * Sets the animacy information for this instance.
636          * @param animacy Can be any of {@link #ANIMACY_ANIMATE} and
637          *     {@link #ANIMACY_INANIMATE}.
638          * @return This instance.
639          */
setAnimacy(String animacy)640         public C setAnimacy(String animacy) {
641             return setStringArgument(TtsSpan.ARG_ANIMACY, animacy);
642         }
643 
644         /**
645          * Sets the multiplicity information for this instance.
646          * @param multiplicity Can be any of
647          *     {@link #MULTIPLICITY_SINGLE}, {@link #MULTIPLICITY_DUAL} and
648          *     {@link #MULTIPLICITY_PLURAL}.
649          * @return This instance.
650          */
setMultiplicity(String multiplicity)651         public C setMultiplicity(String multiplicity) {
652             return setStringArgument(TtsSpan.ARG_MULTIPLICITY, multiplicity);
653         }
654 
655         /**
656          * Sets the grammatical case information for this instance.
657          * @param grammaticalCase Can be any of {@link #CASE_NOMINATIVE},
658          *     {@link #CASE_ACCUSATIVE}, {@link #CASE_DATIVE},
659          *     {@link #CASE_ABLATIVE}, {@link #CASE_GENITIVE},
660          *     {@link #CASE_VOCATIVE}, {@link #CASE_LOCATIVE} and
661          *     {@link #CASE_INSTRUMENTAL}.
662          * @return This instance.
663          */
setCase(String grammaticalCase)664         public C setCase(String grammaticalCase) {
665             return setStringArgument(TtsSpan.ARG_CASE, grammaticalCase);
666         }
667     }
668 
669     /**
670      * A builder for TtsSpans of type {@link #TYPE_TEXT}.
671      */
672     public static class TextBuilder extends SemioticClassBuilder<TextBuilder> {
673 
674         /**
675          * Creates a builder for a TtsSpan of type {@link #TYPE_TEXT}.
676          */
TextBuilder()677         public TextBuilder() {
678             super(TtsSpan.TYPE_TEXT);
679         }
680 
681         /**
682          * Creates a TtsSpan of type {@link #TYPE_TEXT} and sets the
683          * {@link #ARG_TEXT} argument.
684          * @param text The text to be synthesized.
685          * @see #setText(String)
686          */
TextBuilder(String text)687         public TextBuilder(String text) {
688             this();
689             setText(text);
690         }
691 
692         /**
693          * Sets the {@link #ARG_TEXT} argument, the text to be synthesized.
694          * @param text The string that will be synthesized.
695          * @return This instance.
696          */
setText(String text)697         public TextBuilder setText(String text) {
698             return setStringArgument(TtsSpan.ARG_TEXT, text);
699         }
700     }
701 
702     /**
703      * A builder for TtsSpans of type {@link #TYPE_CARDINAL}.
704      */
705     public static class CardinalBuilder
706             extends SemioticClassBuilder<CardinalBuilder> {
707 
708         /**
709          * Creates a builder for a TtsSpan of type {@link #TYPE_CARDINAL}.
710          */
CardinalBuilder()711         public CardinalBuilder() {
712             super(TtsSpan.TYPE_CARDINAL);
713         }
714 
715         /**
716          * Creates a TtsSpan of type {@link #TYPE_CARDINAL} and sets the
717          * {@link #ARG_NUMBER} argument.
718          * @param number The number to synthesize.
719          * @see #setNumber(long)
720          */
CardinalBuilder(long number)721         public CardinalBuilder(long number) {
722             this();
723             setNumber(number);
724         }
725 
726         /**
727          * Creates a TtsSpan of type {@link #TYPE_CARDINAL} and sets the
728          * {@link #ARG_NUMBER} argument.
729          * @param number The number to synthesize.
730          * @see #setNumber(String)
731          */
CardinalBuilder(String number)732         public CardinalBuilder(String number) {
733             this();
734             setNumber(number);
735         }
736 
737         /**
738          * Convenience method that converts the number to a String and set it to
739          * the value for {@link #ARG_NUMBER}.
740          * @param number The number that will be synthesized.
741          * @return This instance.
742          */
setNumber(long number)743         public CardinalBuilder setNumber(long number) {
744             return setNumber(String.valueOf(number));
745         }
746 
747         /**
748          * Sets the {@link #ARG_NUMBER} argument.
749          * @param number A non-empty string of digits with an optional
750          *     leading + or -.
751          * @return This instance.
752          */
setNumber(String number)753         public CardinalBuilder setNumber(String number) {
754             return setStringArgument(TtsSpan.ARG_NUMBER, number);
755         }
756     }
757 
758     /**
759      * A builder for TtsSpans of type {@link #TYPE_ORDINAL}.
760      */
761     public static class OrdinalBuilder
762             extends SemioticClassBuilder<OrdinalBuilder> {
763 
764         /**
765          * Creates a builder for a TtsSpan of type {@link #TYPE_ORDINAL}.
766          */
OrdinalBuilder()767         public OrdinalBuilder() {
768             super(TtsSpan.TYPE_ORDINAL);
769         }
770 
771         /**
772          * Creates a TtsSpan of type {@link #TYPE_ORDINAL} and sets the
773          * {@link #ARG_NUMBER} argument.
774          * @param number The ordinal number to synthesize.
775          * @see #setNumber(long)
776          */
OrdinalBuilder(long number)777         public OrdinalBuilder(long number) {
778             this();
779             setNumber(number);
780         }
781 
782         /**
783          * Creates a TtsSpan of type {@link #TYPE_ORDINAL} and sets the
784          * {@link #ARG_NUMBER} argument.
785          * @param number The number to synthesize.
786          * @see #setNumber(String)
787          */
OrdinalBuilder(String number)788         public OrdinalBuilder(String number) {
789             this();
790             setNumber(number);
791         }
792 
793         /**
794          * Convenience method that converts the number to a String and sets it
795          * to the value for {@link #ARG_NUMBER}.
796          * @param number The ordinal number that will be synthesized.
797          * @return This instance.
798          */
setNumber(long number)799         public OrdinalBuilder setNumber(long number) {
800             return setNumber(String.valueOf(number));
801         }
802 
803         /**
804          * Sets the {@link #ARG_NUMBER} argument.
805          * @param number A non-empty string of digits with an optional
806          *     leading + or -.
807          * @return This instance.
808          */
setNumber(String number)809         public OrdinalBuilder setNumber(String number) {
810             return setStringArgument(TtsSpan.ARG_NUMBER, number);
811         }
812     }
813 
814     /**
815      * A builder for TtsSpans of type {@link #TYPE_DECIMAL}.
816      */
817     public static class DecimalBuilder
818             extends SemioticClassBuilder<DecimalBuilder> {
819 
820         /**
821          * Creates a builder for a TtsSpan of type {@link #TYPE_DECIMAL}.
822          */
DecimalBuilder()823         public DecimalBuilder() {
824             super(TtsSpan.TYPE_DECIMAL);
825         }
826 
827         /**
828          * Creates a TtsSpan of type {@link #TYPE_DECIMAL} and sets the
829          * {@link #ARG_INTEGER_PART} and {@link #ARG_FRACTIONAL_PART} arguments.
830          * @see #setArgumentsFromDouble(double, int, int)
831          */
DecimalBuilder(double number, int minimumFractionDigits, int maximumFractionDigits)832         public DecimalBuilder(double number,
833                               int minimumFractionDigits,
834                               int maximumFractionDigits) {
835             this();
836             setArgumentsFromDouble(number,
837                                    minimumFractionDigits,
838                                    maximumFractionDigits);
839         }
840 
841         /**
842          * Creates a TtsSpan of type {@link #TYPE_DECIMAL} and sets the
843          * {@link #ARG_INTEGER_PART} and {@link #ARG_FRACTIONAL_PART} arguments.
844          */
DecimalBuilder(String integerPart, String fractionalPart)845         public DecimalBuilder(String integerPart, String fractionalPart) {
846             this();
847             setIntegerPart(integerPart);
848             setFractionalPart(fractionalPart);
849         }
850 
851         /**
852          * Convenience method takes a double and a maximum number of fractional
853          * digits, it sets the {@link #ARG_INTEGER_PART} and
854          * {@link #ARG_FRACTIONAL_PART} arguments.
855          * @param number The number to be synthesized.
856          * @param minimumFractionDigits The minimum number of fraction digits
857          *     that are pronounced.
858          * @param maximumFractionDigits The maximum number of fraction digits
859          *     that are pronounced. If maximumFractionDigits <
860          *     minimumFractionDigits then minimumFractionDigits will be assumed
861          *     to be equal to maximumFractionDigits.
862          * @return This instance.
863          */
setArgumentsFromDouble( double number, int minimumFractionDigits, int maximumFractionDigits)864         public DecimalBuilder setArgumentsFromDouble(
865                 double number,
866                 int minimumFractionDigits,
867                 int maximumFractionDigits) {
868             // Format double.
869             NumberFormat formatter = NumberFormat.getInstance(Locale.US);
870             formatter.setMinimumFractionDigits(maximumFractionDigits);
871             formatter.setMaximumFractionDigits(maximumFractionDigits);
872             formatter.setGroupingUsed(false);
873             String str = formatter.format(number);
874 
875             // Split at decimal point.
876             int i = str.indexOf('.');
877             if (i >= 0) {
878                 setIntegerPart(str.substring(0, i));
879                 setFractionalPart(str.substring(i + 1));
880             } else {
881                 setIntegerPart(str);
882             }
883             return this;
884         }
885 
886         /**
887          * Convenience method that converts the number to a String and sets it
888          * to the value for {@link #ARG_INTEGER_PART}.
889          * @param integerPart The integer part of the decimal.
890          * @return This instance.
891          */
setIntegerPart(long integerPart)892         public DecimalBuilder setIntegerPart(long integerPart) {
893             return setIntegerPart(String.valueOf(integerPart));
894         }
895 
896         /**
897          * Sets the {@link #ARG_INTEGER_PART} argument.
898          * @param integerPart A non-empty string of digits with an optional
899          *     leading + or -.
900          * @return This instance.
901          */
setIntegerPart(String integerPart)902         public DecimalBuilder setIntegerPart(String integerPart) {
903             return setStringArgument(TtsSpan.ARG_INTEGER_PART, integerPart);
904         }
905 
906         /**
907          * Sets the {@link #ARG_FRACTIONAL_PART} argument.
908          * @param fractionalPart A non-empty string of digits.
909          * @return This instance.
910          */
setFractionalPart(String fractionalPart)911         public DecimalBuilder setFractionalPart(String fractionalPart) {
912             return setStringArgument(TtsSpan.ARG_FRACTIONAL_PART,
913                                      fractionalPart);
914         }
915     }
916 
917     /**
918      * A builder for TtsSpans of type {@link #TYPE_FRACTION}.
919      */
920     public static class FractionBuilder
921             extends SemioticClassBuilder<FractionBuilder> {
922 
923         /**
924          * Creates a builder for a TtsSpan of type {@link #TYPE_FRACTION}.
925          */
FractionBuilder()926         public FractionBuilder() {
927             super(TtsSpan.TYPE_FRACTION);
928         }
929 
930         /**
931          * Creates a TtsSpan of type {@link #TYPE_FRACTION} and sets the
932          * {@link #ARG_INTEGER_PART}, {@link #ARG_NUMERATOR}, and
933          * {@link #ARG_DENOMINATOR} arguments.
934          */
FractionBuilder(long integerPart, long numerator, long denominator)935         public FractionBuilder(long integerPart,
936                                long numerator,
937                                long denominator) {
938             this();
939             setIntegerPart(integerPart);
940             setNumerator(numerator);
941             setDenominator(denominator);
942         }
943 
944         /**
945          * Convenience method that converts the integer to a String and sets the
946          * argument {@link #ARG_NUMBER}.
947          * @param integerPart The integer part.
948          * @return This instance.
949          */
setIntegerPart(long integerPart)950         public FractionBuilder setIntegerPart(long integerPart) {
951             return setIntegerPart(String.valueOf(integerPart));
952         }
953 
954         /**
955          * Sets the {@link #ARG_INTEGER_PART} argument.
956          * @param integerPart A non-empty string of digits with an optional
957          *     leading + or -.
958          * @return This instance.
959          */
setIntegerPart(String integerPart)960         public FractionBuilder setIntegerPart(String integerPart) {
961             return setStringArgument(TtsSpan.ARG_INTEGER_PART, integerPart);
962         }
963 
964         /**
965          * Convenience method that converts the numerator to a String and sets
966          * the argument {@link #ARG_NUMERATOR}.
967          * @param numerator The numerator.
968          * @return This instance.
969          */
setNumerator(long numerator)970         public FractionBuilder setNumerator(long numerator) {
971             return setNumerator(String.valueOf(numerator));
972         }
973 
974         /**
975          * Sets the {@link #ARG_NUMERATOR} argument.
976          * @param numerator A non-empty string of digits with an optional
977          *     leading + or -.
978          * @return This instance.
979          */
setNumerator(String numerator)980         public FractionBuilder setNumerator(String numerator) {
981             return setStringArgument(TtsSpan.ARG_NUMERATOR, numerator);
982         }
983 
984         /**
985          * Convenience method that converts the denominator to a String and sets
986          * the argument {@link #ARG_DENOMINATOR}.
987          * @param denominator The denominator.
988          * @return This instance.
989          */
setDenominator(long denominator)990         public FractionBuilder setDenominator(long denominator) {
991             return setDenominator(String.valueOf(denominator));
992         }
993 
994         /**
995          * Sets the {@link #ARG_DENOMINATOR} argument.
996          * @param denominator A non-empty string of digits with an optional
997          *     leading + or -.
998          * @return This instance.
999          */
setDenominator(String denominator)1000         public FractionBuilder setDenominator(String denominator) {
1001             return setStringArgument(TtsSpan.ARG_DENOMINATOR, denominator);
1002         }
1003     }
1004 
1005     /**
1006      * A builder for TtsSpans of type {@link #TYPE_MEASURE}.
1007      */
1008     public static class MeasureBuilder
1009             extends SemioticClassBuilder<MeasureBuilder> {
1010 
1011         /**
1012          * Creates a builder for a TtsSpan of type {@link #TYPE_MEASURE}.
1013          */
MeasureBuilder()1014         public MeasureBuilder() {
1015             super(TtsSpan.TYPE_MEASURE);
1016         }
1017 
1018         /**
1019          * Convenience method that converts the number to a String and set it to
1020          * the value for {@link #ARG_NUMBER}.
1021          * @param number The amount of the measure.
1022          * @return This instance.
1023          */
setNumber(long number)1024         public MeasureBuilder setNumber(long number) {
1025             return setNumber(String.valueOf(number));
1026         }
1027 
1028         /**
1029          * Sets the {@link #ARG_NUMBER} argument.
1030          * @param number A non-empty string of digits with an optional
1031          *     leading + or -.
1032          * @return This instance.
1033          */
setNumber(String number)1034         public MeasureBuilder setNumber(String number) {
1035             return setStringArgument(TtsSpan.ARG_NUMBER, number);
1036         }
1037 
1038         /**
1039          * Convenience method that converts the integer part to a String and set
1040          * it to the value for {@link #ARG_INTEGER_PART}.
1041          * @param integerPart The integer part of a decimal or fraction.
1042          * @return This instance.
1043          */
setIntegerPart(long integerPart)1044         public MeasureBuilder setIntegerPart(long integerPart) {
1045             return setIntegerPart(String.valueOf(integerPart));
1046         }
1047 
1048         /**
1049          * Sets the {@link #ARG_INTEGER_PART} argument.
1050          * @param integerPart The integer part of a decimal or fraction; a
1051          * non-empty string of digits with an optional
1052          *     leading + or -.
1053          * @return This instance.
1054          */
setIntegerPart(String integerPart)1055         public MeasureBuilder setIntegerPart(String integerPart) {
1056             return setStringArgument(TtsSpan.ARG_INTEGER_PART, integerPart);
1057         }
1058 
1059         /**
1060          * Sets the {@link #ARG_FRACTIONAL_PART} argument.
1061          * @param fractionalPart The fractional part of a decimal; a non-empty
1062          *     string of digits with an optional leading + or -.
1063          * @return This instance.
1064          */
setFractionalPart(String fractionalPart)1065         public MeasureBuilder setFractionalPart(String fractionalPart) {
1066             return setStringArgument(TtsSpan.ARG_FRACTIONAL_PART,
1067                                      fractionalPart);
1068         }
1069 
1070         /**
1071          * Convenience method that converts the numerator to a String and set it
1072          * to the value for {@link #ARG_NUMERATOR}.
1073          * @param numerator The numerator of a fraction.
1074          * @return This instance.
1075          */
setNumerator(long numerator)1076         public MeasureBuilder setNumerator(long numerator) {
1077             return setNumerator(String.valueOf(numerator));
1078         }
1079 
1080         /**
1081          * Sets the {@link #ARG_NUMERATOR} argument.
1082          * @param numerator The numerator of a fraction; a non-empty string of
1083          *     digits with an optional leading + or -.
1084          * @return This instance.
1085          */
setNumerator(String numerator)1086         public MeasureBuilder setNumerator(String numerator) {
1087             return setStringArgument(TtsSpan.ARG_NUMERATOR, numerator);
1088         }
1089 
1090         /**
1091          * Convenience method that converts the denominator to a String and set
1092          * it to the value for {@link #ARG_DENOMINATOR}.
1093          * @param denominator The denominator of a fraction.
1094          * @return This instance.
1095          */
setDenominator(long denominator)1096         public MeasureBuilder setDenominator(long denominator) {
1097             return setDenominator(String.valueOf(denominator));
1098         }
1099 
1100         /**
1101          * Sets the {@link #ARG_DENOMINATOR} argument.
1102          * @param denominator The denominator of a fraction; a non-empty string
1103          *     of digits with an optional leading + or -.
1104          * @return This instance.
1105          */
setDenominator(String denominator)1106         public MeasureBuilder setDenominator(String denominator) {
1107             return setStringArgument(TtsSpan.ARG_DENOMINATOR, denominator);
1108         }
1109 
1110         /**
1111          * Sets the {@link #ARG_UNIT} argument.
1112          * @param unit The unit of the measure.
1113          * @return This instance.
1114          * @see TtsSpan#ARG_UNIT
1115          */
setUnit(String unit)1116         public MeasureBuilder setUnit(String unit) {
1117             return setStringArgument(TtsSpan.ARG_UNIT, unit);
1118         }
1119     }
1120 
1121     /**
1122      * A builder for TtsSpans of type {@link #TYPE_TIME}.
1123      */
1124     public static class TimeBuilder
1125             extends SemioticClassBuilder<TimeBuilder> {
1126 
1127         /**
1128          * Creates a builder for a TtsSpan of type {@link #TYPE_TIME}.
1129          */
TimeBuilder()1130         public TimeBuilder() {
1131             super(TtsSpan.TYPE_TIME);
1132         }
1133 
1134         /**
1135          * Creates a builder for a TtsSpan of type {@link #TYPE_TIME} and
1136          * sets the {@link #ARG_HOURS} and {@link #ARG_MINUTES} arguments.
1137          */
TimeBuilder(int hours, int minutes)1138         public TimeBuilder(int hours, int minutes) {
1139             this();
1140             setHours(hours);
1141             setMinutes(minutes);
1142         }
1143 
1144         /**
1145          * Sets the {@link #ARG_HOURS} argument.
1146          * @param hours The value to be set for hours. See {@link #ARG_HOURS}.
1147          * @return This instance.
1148          * @see #ARG_HOURS
1149          */
setHours(@ntRangefrom = 0, to = 24) int hours)1150         public TimeBuilder setHours(@IntRange(from = 0, to = 24) int hours) {
1151             return setIntArgument(TtsSpan.ARG_HOURS, hours);
1152         }
1153 
1154         /**
1155          * Sets the {@link #ARG_MINUTES} argument.
1156          * @param minutes The value to be set for minutes. See
1157          *     {@link #ARG_MINUTES}.
1158          * @return This instance.
1159          * @see #ARG_MINUTES
1160          */
setMinutes(@ntRangefrom = 0, to = 59) int minutes)1161         public TimeBuilder setMinutes(@IntRange(from = 0, to = 59) int minutes) {
1162             return setIntArgument(TtsSpan.ARG_MINUTES, minutes);
1163         }
1164 
1165         /**
1166          * Sets the {@link #ARG_SECONDS} argument.
1167          * @param seconds The value to be set for seconds.
1168          * @return This instance.
1169          */
1170         @FlaggedApi(FLAG_TTS_SPAN_DURATION)
1171         @NonNull
setSeconds(@ntRangefrom = 0, to = 59) int seconds)1172         public TimeBuilder setSeconds(@IntRange(from = 0, to = 59) int seconds) {
1173             return setIntArgument(TtsSpan.ARG_SECONDS, seconds);
1174         }
1175     }
1176 
1177     /**
1178      * A builder for TtsSpans of type {@link #TYPE_DURATION}.
1179      */
1180     @FlaggedApi(FLAG_TTS_SPAN_DURATION)
1181     public static class DurationBuilder
1182             extends SemioticClassBuilder<DurationBuilder> {
1183 
1184         /**
1185          * Creates a builder for a TtsSpan of type {@link #TYPE_DURATION}.
1186          */
1187         @FlaggedApi(FLAG_TTS_SPAN_DURATION)
DurationBuilder()1188         public DurationBuilder() {
1189             super(TtsSpan.TYPE_DURATION);
1190         }
1191 
1192         /**
1193          * Sets the {@link #ARG_HOURS} argument.
1194          * @param hours The value to be set for hours.
1195          * @return This instance.
1196          */
1197         @FlaggedApi(FLAG_TTS_SPAN_DURATION)
1198         @NonNull
setHours(int hours)1199         public DurationBuilder setHours(int hours) {
1200             return setIntArgument(TtsSpan.ARG_HOURS, hours);
1201         }
1202 
1203         /**
1204          * Sets the {@link #ARG_MINUTES} argument.
1205          * @param minutes The value to be set for minutes.
1206          * @return This instance.
1207          */
1208         @FlaggedApi(FLAG_TTS_SPAN_DURATION)
1209         @NonNull
setMinutes(int minutes)1210         public DurationBuilder setMinutes(int minutes) {
1211             return setIntArgument(TtsSpan.ARG_MINUTES, minutes);
1212         }
1213 
1214         /**
1215          * Sets the {@link #ARG_SECONDS} argument.
1216          * @param seconds The value to be set for seconds.
1217          * @return This instance.
1218          */
1219         @FlaggedApi(FLAG_TTS_SPAN_DURATION)
1220         @NonNull
setSeconds(int seconds)1221         public DurationBuilder setSeconds(int seconds) {
1222             return setIntArgument(TtsSpan.ARG_SECONDS, seconds);
1223         }
1224     }
1225 
1226 
1227     /**
1228      * A builder for TtsSpans of type {@link #TYPE_DATE}.
1229      */
1230     public static class DateBuilder
1231             extends SemioticClassBuilder<DateBuilder> {
1232 
1233         /**
1234          * Creates a builder for a TtsSpan of type {@link #TYPE_DATE}.
1235          */
DateBuilder()1236         public DateBuilder() {
1237             super(TtsSpan.TYPE_DATE);
1238         }
1239 
1240         /**
1241          * Creates a builder for a TtsSpan of type {@link #TYPE_TIME} and
1242          * possibly sets the {@link #ARG_WEEKDAY}, {@link #ARG_DAY},
1243          * {@link #ARG_MONTH} and {@link #ARG_YEAR} arguments. Pass null to any
1244          * argument to leave it unset.
1245          */
DateBuilder(Integer weekday, Integer day, Integer month, Integer year)1246         public DateBuilder(Integer weekday,
1247                            Integer day,
1248                            Integer month,
1249                            Integer year) {
1250             this();
1251             if (weekday != null) {
1252                 setWeekday(weekday);
1253             }
1254             if (day != null) {
1255                 setDay(day);
1256             }
1257             if (month != null) {
1258                 setMonth(month);
1259             }
1260             if (year != null) {
1261                 setYear(year);
1262             }
1263         }
1264 
1265         /**
1266          * Sets the {@link #ARG_WEEKDAY} argument.
1267          * @param weekday The value to be set for weekday. See
1268          *     {@link #ARG_WEEKDAY}.
1269          * @return This instance.
1270          * @see #ARG_WEEKDAY
1271          */
setWeekday(int weekday)1272         public DateBuilder setWeekday(int weekday) {
1273             return setIntArgument(TtsSpan.ARG_WEEKDAY, weekday);
1274         }
1275 
1276         /**
1277          * Sets the {@link #ARG_DAY} argument.
1278          * @param day The value to be set for day. See {@link #ARG_DAY}.
1279          * @return This instance.
1280          * @see #ARG_DAY
1281          */
setDay(int day)1282         public DateBuilder setDay(int day) {
1283             return setIntArgument(TtsSpan.ARG_DAY, day);
1284         }
1285 
1286         /**
1287          * Sets the {@link #ARG_MONTH} argument.
1288          * @param month The value to be set for month. See {@link #ARG_MONTH}.
1289          * @return This instance.
1290          * @see #ARG_MONTH
1291          */
setMonth(int month)1292         public DateBuilder setMonth(int month) {
1293             return setIntArgument(TtsSpan.ARG_MONTH, month);
1294         }
1295 
1296         /**
1297          * Sets the {@link #ARG_YEAR} argument.
1298          * @param year The value to be set for year. See {@link #ARG_YEAR}.
1299          * @return This instance.
1300          * @see #ARG_YEAR
1301          */
setYear(int year)1302         public DateBuilder setYear(int year) {
1303             return setIntArgument(TtsSpan.ARG_YEAR, year);
1304         }
1305     }
1306 
1307     /**
1308      * A builder for TtsSpans of type {@link #TYPE_MONEY}.
1309      */
1310     public static class MoneyBuilder
1311             extends SemioticClassBuilder<MoneyBuilder> {
1312 
1313         /**
1314          * Creates a TtsSpan of type {@link #TYPE_MONEY}.
1315          */
MoneyBuilder()1316         public MoneyBuilder() {
1317             super(TtsSpan.TYPE_MONEY);
1318         }
1319 
1320         /**
1321          * Convenience method that converts the number to a String and set it to
1322          * the value for {@link #ARG_INTEGER_PART}.
1323          * @param integerPart The integer part of the amount.
1324          * @return This instance.
1325          */
setIntegerPart(long integerPart)1326         public MoneyBuilder setIntegerPart(long integerPart) {
1327             return setIntegerPart(String.valueOf(integerPart));
1328         }
1329 
1330         /**
1331          * Sets the {@link #ARG_INTEGER_PART} argument.
1332          * @param integerPart A non-empty string of digits with an optional
1333          *     leading + or -.
1334          * @return This instance.
1335          */
setIntegerPart(String integerPart)1336         public MoneyBuilder setIntegerPart(String integerPart) {
1337             return setStringArgument(TtsSpan.ARG_INTEGER_PART, integerPart);
1338         }
1339 
1340         /**
1341          * Sets the {@link #ARG_FRACTIONAL_PART} argument.
1342          * @param fractionalPart Can be a string of digits of any size.
1343          * @return This instance.
1344          */
setFractionalPart(String fractionalPart)1345         public MoneyBuilder setFractionalPart(String fractionalPart) {
1346             return setStringArgument(TtsSpan.ARG_FRACTIONAL_PART, fractionalPart);
1347         }
1348 
1349         /**
1350          * Sets the {@link #ARG_CURRENCY} argument.
1351          * @param currency Should be a ISO4217 currency code, e.g. "USD".
1352          * @return This instance.
1353          */
setCurrency(String currency)1354         public MoneyBuilder setCurrency(String currency) {
1355             return setStringArgument(TtsSpan.ARG_CURRENCY, currency);
1356         }
1357 
1358         /**
1359          * Sets the {@link #ARG_QUANTITY} argument.
1360          * @param quantity
1361          * @return This instance.
1362          */
setQuantity(String quantity)1363         public MoneyBuilder setQuantity(String quantity) {
1364             return setStringArgument(TtsSpan.ARG_QUANTITY, quantity);
1365         }
1366     }
1367 
1368     /**
1369      * A builder for TtsSpans of type {@link #TYPE_TELEPHONE}.
1370      */
1371     public static class TelephoneBuilder
1372             extends SemioticClassBuilder<TelephoneBuilder> {
1373 
1374         /**
1375          * Creates a TtsSpan of type {@link #TYPE_TELEPHONE}.
1376          */
TelephoneBuilder()1377         public TelephoneBuilder() {
1378             super(TtsSpan.TYPE_TELEPHONE);
1379         }
1380 
1381         /**
1382          * Creates a TtsSpan of type {@link #TYPE_TELEPHONE} and sets the
1383          * {@link #ARG_NUMBER_PARTS} argument.
1384          */
TelephoneBuilder(String numberParts)1385         public TelephoneBuilder(String numberParts) {
1386             this();
1387             setNumberParts(numberParts);
1388         }
1389 
1390         /**
1391          * Sets the {@link #ARG_COUNTRY_CODE} argument.
1392          * @param countryCode The country code can be a series of digits
1393          * optionally prefixed with a "+".
1394          * @return This instance.
1395          */
setCountryCode(String countryCode)1396         public TelephoneBuilder setCountryCode(String countryCode) {
1397             return setStringArgument(TtsSpan.ARG_COUNTRY_CODE, countryCode);
1398         }
1399 
1400         /**
1401          * Sets the {@link #ARG_NUMBER_PARTS} argument.
1402          * @param numberParts The main telephone number. Can be a series of
1403          *     digits and letters separated by spaces, "/", "-" or ".".
1404          * @return This instance.
1405          */
setNumberParts(String numberParts)1406         public TelephoneBuilder setNumberParts(String numberParts) {
1407             return setStringArgument(TtsSpan.ARG_NUMBER_PARTS, numberParts);
1408         }
1409 
1410         /**
1411          * Sets the {@link #ARG_EXTENSION} argument.
1412          * @param extension The extension can be a series of digits.
1413          * @return This instance.
1414          */
setExtension(String extension)1415         public TelephoneBuilder setExtension(String extension) {
1416             return setStringArgument(TtsSpan.ARG_EXTENSION, extension);
1417         }
1418     }
1419 
1420     /**
1421      * A builder for TtsSpans of type {@link #TYPE_ELECTRONIC}.
1422      */
1423     public static class ElectronicBuilder
1424             extends SemioticClassBuilder<ElectronicBuilder> {
1425 
1426         /**
1427          * Creates a TtsSpan of type {@link #TYPE_ELECTRONIC}.
1428          */
ElectronicBuilder()1429         public ElectronicBuilder() {
1430             super(TtsSpan.TYPE_ELECTRONIC);
1431         }
1432 
1433         /**
1434          * Sets the {@link #ARG_USERNAME} and {@link #ARG_DOMAIN}
1435          *     arguments, representing an email address.
1436          * @param username The part before the @ in the email address.
1437          * @param domain The part after the @ in the email address.
1438          * @return This instance.
1439          */
setEmailArguments(String username, String domain)1440         public ElectronicBuilder setEmailArguments(String username,
1441                                                    String domain) {
1442             return setDomain(domain).setUsername(username);
1443         }
1444 
1445         /**
1446          * Sets the {@link #ARG_PROTOCOL} argument.
1447          * @param protocol The protocol of the URI. Examples are "http" and
1448          *     "ftp".
1449          * @return This instance.
1450          */
setProtocol(String protocol)1451         public ElectronicBuilder setProtocol(String protocol) {
1452             return setStringArgument(TtsSpan.ARG_PROTOCOL, protocol);
1453         }
1454 
1455         /**
1456          * Sets the {@link #ARG_USERNAME} argument.
1457          * @return This instance.
1458          */
setUsername(String username)1459         public ElectronicBuilder setUsername(String username) {
1460             return setStringArgument(TtsSpan.ARG_USERNAME, username);
1461         }
1462 
1463         /**
1464          * Sets the {@link #ARG_PASSWORD} argument.
1465          * @return This instance.
1466          */
setPassword(String password)1467         public ElectronicBuilder setPassword(String password) {
1468             return setStringArgument(TtsSpan.ARG_PASSWORD, password);
1469         }
1470 
1471         /**
1472          * Sets the {@link #ARG_DOMAIN} argument.
1473          * @param domain The domain, for example "source.android.com".
1474          * @return This instance.
1475          */
setDomain(String domain)1476         public ElectronicBuilder setDomain(String domain) {
1477             return setStringArgument(TtsSpan.ARG_DOMAIN, domain);
1478         }
1479 
1480         /**
1481          * Sets the {@link #ARG_PORT} argument.
1482          * @return This instance.
1483          */
setPort(int port)1484         public ElectronicBuilder setPort(int port) {
1485             return setIntArgument(TtsSpan.ARG_PORT, port);
1486         }
1487 
1488         /**
1489          * Sets the {@link #ARG_PATH} argument.
1490          * @param path For example "source/index.html".
1491          * @return This instance.
1492          */
setPath(String path)1493         public ElectronicBuilder setPath(String path) {
1494             return setStringArgument(TtsSpan.ARG_PATH, path);
1495         }
1496 
1497         /**
1498          * Sets the {@link #ARG_QUERY_STRING} argument.
1499          * @param queryString For example "arg=value&argtwo=value".
1500          * @return This instance.
1501          */
setQueryString(String queryString)1502         public ElectronicBuilder setQueryString(String queryString) {
1503             return setStringArgument(TtsSpan.ARG_QUERY_STRING, queryString);
1504         }
1505 
1506         /**
1507          * Sets the {@link #ARG_FRAGMENT_ID} argument.
1508          * @return This instance.
1509          */
setFragmentId(String fragmentId)1510         public ElectronicBuilder setFragmentId(String fragmentId) {
1511             return setStringArgument(TtsSpan.ARG_FRAGMENT_ID, fragmentId);
1512         }
1513     }
1514 
1515     /**
1516      * A builder for TtsSpans of type {@link #TYPE_DIGITS}.
1517      */
1518     public static class DigitsBuilder
1519             extends SemioticClassBuilder<DigitsBuilder> {
1520 
1521         /**
1522          * Creates a builder for a TtsSpan of type {@link #TYPE_DIGITS}.
1523          */
DigitsBuilder()1524         public DigitsBuilder() {
1525             super(TtsSpan.TYPE_DIGITS);
1526         }
1527 
1528         /**
1529          * Creates a builder for a TtsSpan of type {@link #TYPE_DIGITS}
1530          * and sets the {@link #ARG_DIGITS} argument.
1531          */
DigitsBuilder(String digits)1532         public DigitsBuilder(String digits) {
1533             this();
1534             setDigits(digits);
1535         }
1536 
1537         /**
1538          * Sets the {@link #ARG_DIGITS} argument.
1539          * @param digits A string of digits.
1540          * @return This instance.
1541          */
setDigits(String digits)1542         public DigitsBuilder setDigits(String digits) {
1543             return setStringArgument(TtsSpan.ARG_DIGITS, digits);
1544         }
1545     }
1546 
1547     /**
1548      * A builder for TtsSpans of type {@link #TYPE_VERBATIM}.
1549      */
1550     public static class VerbatimBuilder
1551             extends SemioticClassBuilder<VerbatimBuilder> {
1552 
1553         /**
1554          * Creates a builder for a TtsSpan of type {@link #TYPE_VERBATIM}.
1555          */
VerbatimBuilder()1556         public VerbatimBuilder() {
1557             super(TtsSpan.TYPE_VERBATIM);
1558         }
1559 
1560         /**
1561          * Creates a builder for a TtsSpan of type {@link #TYPE_VERBATIM}
1562          * and sets the {@link #ARG_VERBATIM} argument.
1563          */
VerbatimBuilder(String verbatim)1564         public VerbatimBuilder(String verbatim) {
1565             this();
1566             setVerbatim(verbatim);
1567         }
1568 
1569         /**
1570          * Sets the {@link #ARG_VERBATIM} argument.
1571          * @param verbatim A string of characters that will be read verbatim,
1572          *     except whitespace.
1573          * @return This instance.
1574          */
setVerbatim(String verbatim)1575         public VerbatimBuilder setVerbatim(String verbatim) {
1576             return setStringArgument(TtsSpan.ARG_VERBATIM, verbatim);
1577         }
1578     }
1579 }
1580