• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* GENERATED SOURCE. DO NOT MODIFY. */
2 // © 2018 and later: Unicode, Inc. and others.
3 // License & terms of use: http://www.unicode.org/copyright.html
4 package android.icu.text;
5 
6 import java.text.Format.Field;
7 import java.util.Objects;
8 
9 /**
10  * Represents a span of a string containing a given field.
11  *
12  * This class differs from FieldPosition in the following ways:
13  *
14  *   1. It has information on the field category.
15  *   2. It allows you to set constraints to use when iterating over field positions.
16  *   3. It is used for the newer FormattedValue APIs.
17  *
18  * @author sffc
19  */
20 public class ConstrainedFieldPosition {
21 
22     /**
23      * Represents the type of constraint for ConstrainedFieldPosition.
24      *
25      * Constraints are used to control the behavior of iteration in FormattedValue.
26      */
27     private enum ConstraintType {
28         /**
29          * Represents the lack of a constraint.
30          *
31          * This is the value of fConstraint
32          * if no "constrain" methods were called.
33          */
34         NONE,
35 
36         /**
37          * Represents that the field class is constrained.
38          *
39          * This is the value of fConstraint
40          * after {@link #constrainClass} is called.
41          *
42          * FormattedValue implementations should not change the field class when this constraint is active.
43          */
44         CLASS,
45 
46         /**
47          * Represents that the field is constrained.
48          *
49          * This is the value of fConstraint
50          * after {@link #constrainField} is called.
51          *
52          * FormattedValue implementations should not change the field when this constraint is active.
53          */
54         FIELD,
55 
56         /**
57          * Represents that the field value is constrained.
58          *
59          * This is the value of fConstraint
60          * after {@link #constrainField} is called.
61          *
62          * FormattedValue implementations should not change the field or value with this constraint.
63          */
64         VALUE
65     };
66 
67     private ConstraintType fConstraint;
68     private Class<?> fClassConstraint;
69     private Field fField;
70     private Object fValue;
71     private int fStart;
72     private int fLimit;
73     private long fContext;
74 
75     /**
76      * Initializes a CategoryFieldPosition.
77      *
78      * By default, the CategoryFieldPosition has no iteration constraints.
79      */
ConstrainedFieldPosition()80     public ConstrainedFieldPosition() {
81         reset();
82     }
83 
84     /**
85      * Resets this ConstrainedFieldPosition to its initial state, as if it were newly created:
86      *
87      * - Removes any constraints that may have been set on the instance.
88      * - Resets the iteration position.
89      */
reset()90     public void reset() {
91         fConstraint = ConstraintType.NONE;
92         fClassConstraint = Object.class;
93         fField = null;
94         fValue = null;
95         fStart = 0;
96         fLimit = 0;
97         fContext = 0;
98     }
99 
100     /**
101      * Sets a constraint on the field.
102      *
103      * When this instance of ConstrainedFieldPosition is passed to {@link FormattedValue#nextPosition}, positions are
104      * skipped unless they have the given field.
105      *
106      * Any previously set constraints are cleared.
107      *
108      * For example, to loop over all grouping separators:
109      *
110      * <pre>
111      * ConstrainedFieldPosition cfpos;
112      * cfpos.constrainField(NumberFormat.Field.GROUPING_SEPARATOR);
113      * while (fmtval.nextPosition(cfpos)) {
114      *   // handle the grouping separator position
115      * }
116      * </pre>
117      *
118      * Changing the constraint while in the middle of iterating over a FormattedValue
119      * does not generally have well-defined behavior.
120      *
121      * @param field
122      *            The field to fix when iterating.
123      */
constrainField(Field field)124     public void constrainField(Field field) {
125         if (field == null) {
126             throw new IllegalArgumentException("Cannot constrain on null field");
127         }
128         fConstraint = ConstraintType.FIELD;
129         fClassConstraint = Object.class;
130         fField = field;
131         fValue = null;
132     }
133 
134     /**
135      * Sets a constraint on the field class.
136      *
137      * When this instance of ConstrainedFieldPosition is passed to {@link FormattedValue#nextPosition}, positions are
138      * skipped unless the field is an instance of the class constraint, including subclasses.
139      *
140      * Any previously set constraints are cleared.
141      *
142      * For example, to loop over only the number-related fields:
143      *
144      * <pre>
145      * ConstrainedFieldPosition cfpos;
146      * cfpos.constrainClass(NumberFormat.Field.class);
147      * while (fmtval.nextPosition(cfpos)) {
148      *   // handle the number-related field position
149      * }
150      * </pre>
151      *
152      * @param classConstraint
153      *            The field class to fix when iterating.
154      */
constrainClass(Class<?> classConstraint)155     public void constrainClass(Class<?> classConstraint) {
156         if (classConstraint == null) {
157             throw new IllegalArgumentException("Cannot constrain on null field class");
158         }
159         fConstraint = ConstraintType.CLASS;
160         fClassConstraint = classConstraint;
161         fField = null;
162         fValue = null;
163     }
164 
165     /**
166      * Sets a constraint on field and field value.
167      *
168      * When this instance of ConstrainedFieldPosition is passed to {@link FormattedValue#nextPosition}, positions are
169      * skipped unless both the field and the field value are equal.
170      *
171      * Any previously set constraints are cleared.
172      *
173      * For example, to find the span a date interval corresponding to the first date:
174      *
175      * <pre>
176      * ConstrainedFieldPosition cfpos;
177      * cfpos.constrainFieldAndValue(DateIntervalFormat.SpanField.DATE_INTERVAL_SPAN, 0);
178      * while (fmtval.nextPosition(cfpos)) {
179      *   // handle the span of the first date in the date interval
180      * }
181      * </pre>
182      *
183      * @param field The field to fix when iterating.
184      * @param fieldValue The field value to fix when iterating.
185      * @deprecated This API is for technology preview and might be changed or removed in a future release.
186      * @hide draft / provisional / internal are hidden on Android
187      */
188     @Deprecated
constrainFieldAndValue(Field field, Object fieldValue)189     public void constrainFieldAndValue(Field field, Object fieldValue) {
190         fConstraint = ConstraintType.VALUE;
191         fClassConstraint = Object.class;
192         fField = field;
193         fValue = fieldValue;
194     }
195 
196     /**
197      * Gets the field for the current position.
198      *
199      * The return value is well-defined and non-null only after
200      * FormattedValue#nextPosition returns true.
201      *
202      * @return The field saved in the instance. See above for null conditions.
203      */
getField()204     public Field getField() {
205         return fField;
206     }
207 
208     /**
209      * Gets the INCLUSIVE start index for the current position.
210      *
211      * The return value is well-defined only after FormattedValue#nextPosition returns true.
212      *
213      * @return The start index saved in the instance.
214      */
getStart()215     public int getStart() {
216         return fStart;
217     }
218 
219     /**
220      * Gets the EXCLUSIVE end index stored for the current position.
221      *
222      * The return value is well-defined only after FormattedValue#nextPosition returns true.
223      *
224      * @return The end index saved in the instance.
225      */
getLimit()226     public int getLimit() {
227         return fLimit;
228     }
229 
230     /**
231      * Gets the value associated with the current field position. The field value is often not set.
232      *
233      * The return value is well-defined only after FormattedValue#nextPosition returns true.
234      *
235      * @return The value for the current position. Might be null.
236      */
getFieldValue()237     public Object getFieldValue() {
238         return fValue;
239     }
240 
241     /**
242      * Gets an int64 that FormattedValue implementations may use for storage.
243      *
244      * The initial value is zero.
245      *
246      * Users of FormattedValue should not need to call this method.
247      *
248      * @return The current iteration context from {@link #setInt64IterationContext}.
249      */
getInt64IterationContext()250     public long getInt64IterationContext() {
251         return fContext;
252     }
253 
254     /**
255      * Sets an int64 that FormattedValue implementations may use for storage.
256      *
257      * Intended to be used by FormattedValue implementations.
258      *
259      * @param context
260      *            The new iteration context.
261      */
setInt64IterationContext(long context)262     public void setInt64IterationContext(long context) {
263         fContext = context;
264     }
265 
266     /**
267      * Sets new values for the primary public getters.
268      *
269      * Intended to be used by FormattedValue implementations.
270      *
271      * It is up to the implementation to ensure that the user-requested
272      * constraints are satisfied. This method does not check!
273      *
274      * @param field
275      *            The new field.
276      * @param value
277      *            The new field value. Should be null if there is no value.
278      * @param start
279      *            The new inclusive start index.
280      * @param limit
281      *            The new exclusive end index.
282      */
setState(Field field, Object value, int start, int limit)283     public void setState(Field field, Object value, int start, int limit) {
284         // Check matchesField only as an assertion (debug build)
285         if (field != null) {
286             assert matchesField(field, value);
287         }
288 
289         fField = field;
290         fValue = value;
291         fStart = start;
292         fLimit = limit;
293     }
294 
295     /**
296      * Determines whether a given field and value should be included given the
297      * constraints.
298      *
299      * Intended to be used by FormattedValue implementations.
300      *
301      * @param field The field to test.
302      * @param fieldValue The field value to test. Should be null if there is no value.
303      * @return Whether the field should be included given the constraints.
304      */
matchesField(Field field, Object fieldValue)305     public boolean matchesField(Field field, Object fieldValue) {
306         if (field == null) {
307             throw new IllegalArgumentException("field must not be null");
308         }
309         switch (fConstraint) {
310         case NONE:
311             return true;
312         case CLASS:
313             return fClassConstraint.isAssignableFrom(field.getClass());
314         case FIELD:
315             return fField == field;
316         case VALUE:
317             // Note: Objects.equals is Android API level 19 and Java 1.7
318             return fField == field && Objects.equals(fValue, fieldValue);
319         default:
320             throw new AssertionError();
321         }
322     }
323 
324     /**
325      * {@inheritDoc}
326      */
327     @Override
toString()328     public String toString() {
329         StringBuilder sb = new StringBuilder();
330         sb.append("CFPos[");
331         sb.append(fStart);
332         sb.append('-');
333         sb.append(fLimit);
334         sb.append(' ');
335         sb.append(fField);
336         sb.append(']');
337         return sb.toString();
338     }
339 }
340