1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one or more
3  * contributor license agreements.  See the NOTICE file distributed with
4  * this work for additional information regarding copyright ownership.
5  * The ASF licenses this file to You under the Apache License, Version 2.0
6  * (the "License"); you may not use this file except in compliance with
7  * the License.  You may obtain a copy of the License at
8  *
9  *     http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 
18 package java.text;
19 
20 import java.io.InvalidObjectException;
21 import java.io.Serializable;
22 import java.lang.reflect.Field;
23 import java.lang.reflect.Modifier;
24 import java.util.Map;
25 import java.util.Set;
26 
27 /**
28  * Extends the
29  * {@link CharacterIterator} interface, adding support for iterating over
30  * attributes and not only characters. An
31  * {@code AttributedCharacterIterator} also allows the user to find runs and
32  * their limits. Runs are defined as ranges of characters that all have the same
33  * attributes with the same values.
34  */
35 public interface AttributedCharacterIterator extends CharacterIterator {
36 
37     /**
38      * Defines keys for text attributes.
39      */
40     public static class Attribute implements Serializable {
41 
42         private static final long serialVersionUID = -9142742483513960612L;
43 
44         /**
45          * This attribute marks segments from an input method. Most input
46          * methods create these segments for words.
47          *
48          * The value objects are of the type {@code Annotation} which contain
49          * {@code null}.
50          */
51         public static final Attribute INPUT_METHOD_SEGMENT = new Attribute("input_method_segment");
52 
53         /**
54          * The attribute describing the language of a character. The value
55          * objects are of type {@code Locale} or a subtype of it.
56          */
57         public static final Attribute LANGUAGE = new Attribute("language");
58 
59         /**
60          * For languages that have different reading directions of text (like
61          * Japanese), this attribute allows to define which reading should be
62          * used. The value objects are of type {@code Annotation} which
63          * contain a {@code String}.
64          */
65         public static final Attribute READING = new Attribute("reading");
66 
67         private String name;
68 
69         /**
70          * The constructor for an {@code Attribute} with the name passed.
71          *
72          * @param name
73          *            the name of the new {@code Attribute}.
74          */
Attribute(String name)75         protected Attribute(String name) {
76             this.name = name;
77         }
78 
79         /**
80          * Compares this attribute with the specified object. Checks if both
81          * objects are the same instance. It is defined final so all subclasses
82          * have the same behavior for this method.
83          *
84          * @param object
85          *            the object to compare against.
86          * @return {@code true} if the object passed is equal to this instance;
87          *         {@code false} otherwise.
88          */
89         @Override
equals(Object object)90         public final boolean equals(Object object) {
91             return this == object;
92         }
93 
94         /**
95          * Returns the name of this attribute.
96          *
97          * @return the name of this attribute.
98          */
getName()99         protected String getName() {
100             return name;
101         }
102 
103         /**
104          * Calculates the hash code for objects of type {@code Attribute}. It
105          * is defined final so all sub types calculate their hash code
106          * identically.
107          *
108          * @return the hash code for this instance of {@code Attribute}.
109          */
110         @Override
hashCode()111         public final int hashCode() {
112             return super.hashCode();
113         }
114 
115         /**
116          * Resolves a deserialized instance to the correct constant attribute.
117          *
118          * @return the {@code Attribute} this instance represents.
119          * @throws InvalidObjectException
120          *             if this instance is not of type {@code Attribute.class}
121          *             or if it is not a known {@code Attribute}.
122          */
readResolve()123         protected Object readResolve() throws InvalidObjectException {
124             /*
125              * This class is used like Java enums, where all instances are
126              * defined as fields of their own class. To preserve identity
127              * equality, resolve to the canonical instance when deserialized.
128              */
129             try {
130                 for (Field field : getClass().getFields()) {
131                     if (field.getType() == getClass() && Modifier.isStatic(field.getModifiers())) {
132                         Attribute candidate = (Attribute) field.get(null);
133                         if (name.equals(candidate.name)) {
134                             return candidate;
135                         }
136                     }
137                 }
138             } catch (IllegalAccessException e) {
139             }
140             throw new InvalidObjectException("Failed to resolve " + this);
141         }
142 
143         /**
144          * Returns the name of the class followed by a "(", the name of the
145          * attribute, and a ")".
146          *
147          * @return the string representing this instance.
148          */
149         @Override
toString()150         public String toString() {
151             return getClass().getName() + '(' + getName() + ')';
152         }
153     }
154 
155     /**
156      * Returns a set of attributes present in the {@code
157      * AttributedCharacterIterator}. An empty set is returned if no attributes
158      * were defined.
159      *
160      * @return a set of attribute keys; may be empty.
161      */
getAllAttributeKeys()162     public Set<Attribute> getAllAttributeKeys();
163 
164     /**
165      * Returns the value stored in the attribute for the current character. If
166      * the attribute was not defined then {@code null} is returned.
167      *
168      * @param attribute the attribute for which the value should be returned.
169      * @return the value of the requested attribute for the current character or
170      *         {@code null} if it was not defined.
171      */
getAttribute(Attribute attribute)172     public Object getAttribute(Attribute attribute);
173 
174     /**
175      * Returns a map of all attributes of the current character. If no
176      * attributes were defined for the current character then an empty map is
177      * returned.
178      *
179      * @return a map of all attributes for the current character or an empty
180      *         map.
181      */
getAttributes()182     public Map<Attribute, Object> getAttributes();
183 
184     /**
185      * Returns the index of the last character in the run having the same
186      * attributes as the current character.
187      *
188      * @return the index of the last character of the current run.
189      */
getRunLimit()190     public int getRunLimit();
191 
192     /**
193      * Returns the index of the last character in the run that has the same
194      * attribute value for the given attribute as the current character.
195      *
196      * @param attribute
197      *            the attribute which the run is based on.
198      * @return the index of the last character of the current run.
199      */
getRunLimit(Attribute attribute)200     public int getRunLimit(Attribute attribute);
201 
202     /**
203      * Returns the index of the last character in the run that has the same
204      * attribute values for the attributes in the set as the current character.
205      *
206      * @param attributes
207      *            the set of attributes which the run is based on.
208      * @return the index of the last character of the current run.
209      */
getRunLimit(Set<? extends Attribute> attributes)210     public int getRunLimit(Set<? extends Attribute> attributes);
211 
212     /**
213      * Returns the index of the first character in the run that has the same
214      * attributes as the current character.
215      *
216      * @return the index of the last character of the current run.
217      */
getRunStart()218     public int getRunStart();
219 
220     /**
221      * Returns the index of the first character in the run that has the same
222      * attribute value for the given attribute as the current character.
223      *
224      * @param attribute
225      *            the attribute which the run is based on.
226      * @return the index of the last character of the current run.
227      */
getRunStart(Attribute attribute)228     public int getRunStart(Attribute attribute);
229 
230     /**
231      * Returns the index of the first character in the run that has the same
232      * attribute values for the attributes in the set as the current character.
233      *
234      * @param attributes
235      *            the set of attributes which the run is based on.
236      * @return the index of the last character of the current run.
237      */
getRunStart(Set<? extends Attribute> attributes)238     public int getRunStart(Set<? extends Attribute> attributes);
239 }
240