| /* GENERATED SOURCE. DO NOT MODIFY. */ |
| // © 2018 and later: Unicode, Inc. and others. |
| // License & terms of use: http://www.unicode.org/copyright.html |
| package android.icu.text; |
| |
| import java.text.Format.Field; |
| import java.util.Objects; |
| |
| /** |
| * Represents a span of a string containing a given field. |
| * |
| * This class differs from FieldPosition in the following ways: |
| * |
| * 1. It has information on the field category. |
| * 2. It allows you to set constraints to use when iterating over field positions. |
| * 3. It is used for the newer FormattedValue APIs. |
| * |
| * @author sffc |
| */ |
| public class ConstrainedFieldPosition { |
| |
| /** |
| * Represents the type of constraint for ConstrainedFieldPosition. |
| * |
| * Constraints are used to control the behavior of iteration in FormattedValue. |
| */ |
| private enum ConstraintType { |
| /** |
| * Represents the lack of a constraint. |
| * |
| * This is the value of fConstraint |
| * if no "constrain" methods were called. |
| */ |
| NONE, |
| |
| /** |
| * Represents that the field class is constrained. |
| * |
| * This is the value of fConstraint |
| * after {@link #constrainClass} is called. |
| * |
| * FormattedValue implementations should not change the field class when this constraint is active. |
| */ |
| CLASS, |
| |
| /** |
| * Represents that the field is constrained. |
| * |
| * This is the value of fConstraint |
| * after {@link #constrainField} is called. |
| * |
| * FormattedValue implementations should not change the field when this constraint is active. |
| */ |
| FIELD, |
| |
| /** |
| * Represents that the field value is constrained. |
| * |
| * This is the value of fConstraint |
| * after {@link #constrainField} is called. |
| * |
| * FormattedValue implementations should not change the field or value with this constraint. |
| */ |
| VALUE |
| }; |
| |
| private ConstraintType fConstraint; |
| private Class<?> fClassConstraint; |
| private Field fField; |
| private Object fValue; |
| private int fStart; |
| private int fLimit; |
| private long fContext; |
| |
| /** |
| * Initializes a CategoryFieldPosition. |
| * |
| * By default, the CategoryFieldPosition has no iteration constraints. |
| */ |
| public ConstrainedFieldPosition() { |
| reset(); |
| } |
| |
| /** |
| * Resets this ConstrainedFieldPosition to its initial state, as if it were newly created: |
| * |
| * - Removes any constraints that may have been set on the instance. |
| * - Resets the iteration position. |
| */ |
| public void reset() { |
| fConstraint = ConstraintType.NONE; |
| fClassConstraint = Object.class; |
| fField = null; |
| fValue = null; |
| fStart = 0; |
| fLimit = 0; |
| fContext = 0; |
| } |
| |
| /** |
| * Sets a constraint on the field. |
| * |
| * When this instance of ConstrainedFieldPosition is passed to {@link FormattedValue#nextPosition}, positions are |
| * skipped unless they have the given field. |
| * |
| * Any previously set constraints are cleared. |
| * |
| * For example, to loop over all grouping separators: |
| * |
| * <pre> |
| * ConstrainedFieldPosition cfpos; |
| * cfpos.constrainField(NumberFormat.Field.GROUPING_SEPARATOR); |
| * while (fmtval.nextPosition(cfpos)) { |
| * // handle the grouping separator position |
| * } |
| * </pre> |
| * |
| * Changing the constraint while in the middle of iterating over a FormattedValue |
| * does not generally have well-defined behavior. |
| * |
| * @param field |
| * The field to fix when iterating. |
| */ |
| public void constrainField(Field field) { |
| if (field == null) { |
| throw new IllegalArgumentException("Cannot constrain on null field"); |
| } |
| fConstraint = ConstraintType.FIELD; |
| fClassConstraint = Object.class; |
| fField = field; |
| fValue = null; |
| } |
| |
| /** |
| * Sets a constraint on the field class. |
| * |
| * When this instance of ConstrainedFieldPosition is passed to {@link FormattedValue#nextPosition}, positions are |
| * skipped unless the field is an instance of the class constraint, including subclasses. |
| * |
| * Any previously set constraints are cleared. |
| * |
| * For example, to loop over only the number-related fields: |
| * |
| * <pre> |
| * ConstrainedFieldPosition cfpos; |
| * cfpos.constrainClass(NumberFormat.Field.class); |
| * while (fmtval.nextPosition(cfpos)) { |
| * // handle the number-related field position |
| * } |
| * </pre> |
| * |
| * @param classConstraint |
| * The field class to fix when iterating. |
| */ |
| public void constrainClass(Class<?> classConstraint) { |
| if (classConstraint == null) { |
| throw new IllegalArgumentException("Cannot constrain on null field class"); |
| } |
| fConstraint = ConstraintType.CLASS; |
| fClassConstraint = classConstraint; |
| fField = null; |
| fValue = null; |
| } |
| |
| /** |
| * Sets a constraint on field and field value. |
| * |
| * When this instance of ConstrainedFieldPosition is passed to {@link FormattedValue#nextPosition}, positions are |
| * skipped unless both the field and the field value are equal. |
| * |
| * Any previously set constraints are cleared. |
| * |
| * For example, to find the span a date interval corresponding to the first date: |
| * |
| * <pre> |
| * ConstrainedFieldPosition cfpos; |
| * cfpos.constrainFieldAndValue(DateIntervalFormat.SpanField.DATE_INTERVAL_SPAN, 0); |
| * while (fmtval.nextPosition(cfpos)) { |
| * // handle the span of the first date in the date interval |
| * } |
| * </pre> |
| * |
| * @param field The field to fix when iterating. |
| * @param fieldValue The field value to fix when iterating. |
| * @deprecated This API is for technology preview and might be changed or removed in a future release. |
| * @hide draft / provisional / internal are hidden on Android |
| */ |
| @Deprecated |
| public void constrainFieldAndValue(Field field, Object fieldValue) { |
| fConstraint = ConstraintType.VALUE; |
| fClassConstraint = Object.class; |
| fField = field; |
| fValue = fieldValue; |
| } |
| |
| /** |
| * Gets the field for the current position. |
| * |
| * The return value is well-defined and non-null only after |
| * FormattedValue#nextPosition returns true. |
| * |
| * @return The field saved in the instance. See above for null conditions. |
| */ |
| public Field getField() { |
| return fField; |
| } |
| |
| /** |
| * Gets the INCLUSIVE start index for the current position. |
| * |
| * The return value is well-defined only after FormattedValue#nextPosition returns true. |
| * |
| * @return The start index saved in the instance. |
| */ |
| public int getStart() { |
| return fStart; |
| } |
| |
| /** |
| * Gets the EXCLUSIVE end index stored for the current position. |
| * |
| * The return value is well-defined only after FormattedValue#nextPosition returns true. |
| * |
| * @return The end index saved in the instance. |
| */ |
| public int getLimit() { |
| return fLimit; |
| } |
| |
| /** |
| * Gets the value associated with the current field position. The field value is often not set. |
| * |
| * The return value is well-defined only after FormattedValue#nextPosition returns true. |
| * |
| * @return The value for the current position. Might be null. |
| */ |
| public Object getFieldValue() { |
| return fValue; |
| } |
| |
| /** |
| * Gets an int64 that FormattedValue implementations may use for storage. |
| * |
| * The initial value is zero. |
| * |
| * Users of FormattedValue should not need to call this method. |
| * |
| * @return The current iteration context from {@link #setInt64IterationContext}. |
| */ |
| public long getInt64IterationContext() { |
| return fContext; |
| } |
| |
| /** |
| * Sets an int64 that FormattedValue implementations may use for storage. |
| * |
| * Intended to be used by FormattedValue implementations. |
| * |
| * @param context |
| * The new iteration context. |
| */ |
| public void setInt64IterationContext(long context) { |
| fContext = context; |
| } |
| |
| /** |
| * Sets new values for the primary public getters. |
| * |
| * Intended to be used by FormattedValue implementations. |
| * |
| * It is up to the implementation to ensure that the user-requested |
| * constraints are satisfied. This method does not check! |
| * |
| * @param field |
| * The new field. |
| * @param value |
| * The new field value. Should be null if there is no value. |
| * @param start |
| * The new inclusive start index. |
| * @param limit |
| * The new exclusive end index. |
| */ |
| public void setState(Field field, Object value, int start, int limit) { |
| // Check matchesField only as an assertion (debug build) |
| if (field != null) { |
| assert matchesField(field, value); |
| } |
| |
| fField = field; |
| fValue = value; |
| fStart = start; |
| fLimit = limit; |
| } |
| |
| /** |
| * Determines whether a given field and value should be included given the |
| * constraints. |
| * |
| * Intended to be used by FormattedValue implementations. |
| * |
| * @param field The field to test. |
| * @param fieldValue The field value to test. Should be null if there is no value. |
| * @return Whether the field should be included given the constraints. |
| */ |
| public boolean matchesField(Field field, Object fieldValue) { |
| if (field == null) { |
| throw new IllegalArgumentException("field must not be null"); |
| } |
| switch (fConstraint) { |
| case NONE: |
| return true; |
| case CLASS: |
| return fClassConstraint.isAssignableFrom(field.getClass()); |
| case FIELD: |
| return fField == field; |
| case VALUE: |
| // Note: Objects.equals is Android API level 19 and Java 1.7 |
| return fField == field && Objects.equals(fValue, fieldValue); |
| default: |
| throw new AssertionError(); |
| } |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| @Override |
| public String toString() { |
| StringBuilder sb = new StringBuilder(); |
| sb.append("CFPos["); |
| sb.append(fStart); |
| sb.append('-'); |
| sb.append(fLimit); |
| sb.append(' '); |
| sb.append(fField); |
| sb.append(']'); |
| return sb.toString(); |
| } |
| } |