/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package java.text;
import java.io.InvalidObjectException;
import java.io.Serializable;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.Map;
import java.util.Set;
/**
* Extends the
* {@link CharacterIterator} interface, adding support for iterating over
* attributes and not only characters. An
* {@code AttributedCharacterIterator} also allows the user to find runs and
* their limits. Runs are defined as ranges of characters that all have the same
* attributes with the same values.
*/
public interface AttributedCharacterIterator extends CharacterIterator {
/**
* Defines keys for text attributes.
*/
public static class Attribute implements Serializable {
private static final long serialVersionUID = -9142742483513960612L;
/**
* This attribute marks segments from an input method. Most input
* methods create these segments for words.
*
* The value objects are of the type {@code Annotation} which contain
* {@code null}.
*/
public static final Attribute INPUT_METHOD_SEGMENT = new Attribute("input_method_segment");
/**
* The attribute describing the language of a character. The value
* objects are of type {@code Locale} or a subtype of it.
*/
public static final Attribute LANGUAGE = new Attribute("language");
/**
* For languages that have different reading directions of text (like
* Japanese), this attribute allows to define which reading should be
* used. The value objects are of type {@code Annotation} which
* contain a {@code String}.
*/
public static final Attribute READING = new Attribute("reading");
private String name;
/**
* The constructor for an {@code Attribute} with the name passed.
*
* @param name
* the name of the new {@code Attribute}.
*/
protected Attribute(String name) {
this.name = name;
}
/**
* Compares this attribute with the specified object. Checks if both
* objects are the same instance. It is defined final so all subclasses
* have the same behavior for this method.
*
* @param object
* the object to compare against.
* @return {@code true} if the object passed is equal to this instance;
* {@code false} otherwise.
*/
@Override
public final boolean equals(Object object) {
return this == object;
}
/**
* Returns the name of this attribute.
*
* @return the name of this attribute.
*/
protected String getName() {
return name;
}
/**
* Calculates the hash code for objects of type {@code Attribute}. It
* is defined final so all sub types calculate their hash code
* identically.
*
* @return the hash code for this instance of {@code Attribute}.
*/
@Override
public final int hashCode() {
return super.hashCode();
}
/**
* Resolves a deserialized instance to the correct constant attribute.
*
* @return the {@code Attribute} this instance represents.
* @throws InvalidObjectException
* if this instance is not of type {@code Attribute.class}
* or if it is not a known {@code Attribute}.
*/
protected Object readResolve() throws InvalidObjectException {
/*
* This class is used like Java enums, where all instances are
* defined as fields of their own class. To preserve identity
* equality, resolve to the canonical instance when deserialized.
*/
try {
for (Field field : getClass().getFields()) {
if (field.getType() == getClass() && Modifier.isStatic(field.getModifiers())) {
Attribute candidate = (Attribute) field.get(null);
if (name.equals(candidate.name)) {
return candidate;
}
}
}
} catch (IllegalAccessException e) {
}
throw new InvalidObjectException("Failed to resolve " + this);
}
/**
* Returns the name of the class followed by a "(", the name of the
* attribute, and a ")".
*
* @return the string representing this instance.
*/
@Override
public String toString() {
return getClass().getName() + '(' + getName() + ')';
}
}
/**
* Returns a set of attributes present in the {@code
* AttributedCharacterIterator}. An empty set is returned if no attributes
* were defined.
*
* @return a set of attribute keys; may be empty.
*/
public Set<Attribute> getAllAttributeKeys();
/**
* Returns the value stored in the attribute for the current character. If
* the attribute was not defined then {@code null} is returned.
*
* @param attribute the attribute for which the value should be returned.
* @return the value of the requested attribute for the current character or
* {@code null} if it was not defined.
*/
public Object getAttribute(Attribute attribute);
/**
* Returns a map of all attributes of the current character. If no
* attributes were defined for the current character then an empty map is
* returned.
*
* @return a map of all attributes for the current character or an empty
* map.
*/
public Map<Attribute, Object> getAttributes();
/**
* Returns the index of the last character in the run having the same
* attributes as the current character.
*
* @return the index of the last character of the current run.
*/
public int getRunLimit();
/**
* Returns the index of the last character in the run that has the same
* attribute value for the given attribute as the current character.
*
* @param attribute
* the attribute which the run is based on.
* @return the index of the last character of the current run.
*/
public int getRunLimit(Attribute attribute);
/**
* Returns the index of the last character in the run that has the same
* attribute values for the attributes in the set as the current character.
*
* @param attributes
* the set of attributes which the run is based on.
* @return the index of the last character of the current run.
*/
public int getRunLimit(Set<? extends Attribute> attributes);
/**
* Returns the index of the first character in the run that has the same
* attributes as the current character.
*
* @return the index of the last character of the current run.
*/
public int getRunStart();
/**
* Returns the index of the first character in the run that has the same
* attribute value for the given attribute as the current character.
*
* @param attribute
* the attribute which the run is based on.
* @return the index of the last character of the current run.
*/
public int getRunStart(Attribute attribute);
/**
* Returns the index of the first character in the run that has the same
* attribute values for the attributes in the set as the current character.
*
* @param attributes
* the set of attributes which the run is based on.
* @return the index of the last character of the current run.
*/
public int getRunStart(Set<? extends Attribute> attributes);
}