com.ibm.icu.impl.FormattedValueFieldPositionIteratorImpl Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of icu4j Show documentation
Show all versions of icu4j Show documentation
International Component for Unicode for Java (ICU4J) is a mature, widely used Java library
providing Unicode and Globalization support
// © 2019 and later: Unicode, Inc. and others.
// License & terms of use: http://www.unicode.org/copyright.html
package com.ibm.icu.impl;
import java.text.AttributedCharacterIterator;
import java.text.AttributedString;
import java.text.FieldPosition;
import java.text.Format;
import java.util.List;
import com.ibm.icu.text.ConstrainedFieldPosition;
/**
* Implementation of FormattedValue based on FieldPositionIterator.
*
* In C++, this implements FormattedValue. In Java, it is a stateless
* collection of static functions to avoid having to use nested objects.
*/
public class FormattedValueFieldPositionIteratorImpl {
/** Do not construct instances of this class */
private FormattedValueFieldPositionIteratorImpl() {}
/** Helper class to keep track of fields with values in Java */
private static class FieldWithValue extends Format.Field {
private static final long serialVersionUID = -3850076447157793465L;
public final Format.Field field;
public final int value;
public FieldWithValue(Format.Field field, int value) {
super(field.toString());
this.field = field;
this.value = value;
}
}
public static boolean nextPosition(List attributes, ConstrainedFieldPosition cfpos) {
int numFields = attributes.size();
int i = (int) cfpos.getInt64IterationContext();
for (; i < numFields; i++) {
FieldPosition fpos = attributes.get(i);
Format.Field field = fpos.getFieldAttribute();
Object value = null;
if (field instanceof FieldWithValue) {
value = ((FieldWithValue) field).value;
field = ((FieldWithValue) field).field;
}
if (cfpos.matchesField(field, value)) {
int start = fpos.getBeginIndex();
int limit = fpos.getEndIndex();
cfpos.setState(field, value, start, limit);
break;
}
}
cfpos.setInt64IterationContext(i == numFields ? i : i + 1);
return i < numFields;
}
public static AttributedCharacterIterator toCharacterIterator(CharSequence cs, List attributes) {
AttributedString as = new AttributedString(cs.toString());
// add attributes to the AttributedString
for (int i = 0; i < attributes.size(); i++) {
FieldPosition fp = attributes.get(i);
Format.Field field = fp.getFieldAttribute();
Object value = field;
if (field instanceof FieldWithValue) {
value = ((FieldWithValue) field).value;
field = ((FieldWithValue) field).field;
}
as.addAttribute(field, value, fp.getBeginIndex(), fp.getEndIndex());
}
// return the CharacterIterator from AttributedString
return as.getIterator();
}
public static void addOverlapSpans(List attributes, Format.Field spanField, int firstIndex) {
// In order to avoid fancy data structures, this is an O(N^2) algorithm,
// which should be fine for all real-life applications of this function.
int s1a = Integer.MAX_VALUE;
int s1b = 0;
int s2a = Integer.MAX_VALUE;
int s2b = 0;
int numFields = attributes.size();
for (int i = 0; i attributes) {
// Use bubble sort, O(N^2) but easy and no fancy data structures.
int numFields = attributes.size();
while (true) {
boolean isSorted = true;
for (int i=0; i higher rank
comparison = fp2.getBeginIndex() - fp1.getBeginIndex();
} else if (fp1.getEndIndex() != fp2.getEndIndex()) {
// Higher length (end index) -> lower rank
comparison = fp1.getEndIndex() - fp2.getEndIndex();
} else if (fp1.getFieldAttribute() != fp2.getFieldAttribute()) {
// Span category -> lower rank
// Pick other orders arbitrarily
boolean fp1isSpan = fp1.getFieldAttribute() instanceof FieldWithValue;
boolean fp2isSpan = fp2.getFieldAttribute() instanceof FieldWithValue;
if (fp1isSpan && !fp2isSpan) {
comparison = 1;
} else if (fp2isSpan && !fp1isSpan) {
comparison = -1;
} else {
comparison = fp1.hashCode() - fp2.hashCode();
}
}
if (comparison < 0) {
// Perform a swap
isSorted = false;
attributes.set(i, fp2);
attributes.set(i + 1, fp1);
}
}
if (isSorted) {
break;
}
}
}
}