340 lines
10 KiB
Java
340 lines
10 KiB
Java
![]() |
/* 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();
|
||
|
}
|
||
|
}
|