1 /* 2 * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 /* @test 25 * @bug 4139771 26 * @summary test all aspects of AttributedString class 27 */ 28 29 package test.java.text.AttributedString; 30 31 import java.text.Annotation; 32 import java.text.AttributedCharacterIterator; 33 import java.text.AttributedCharacterIterator.Attribute; 34 import java.text.AttributedString; 35 import java.text.CharacterIterator; 36 import java.util.HashSet; 37 import java.util.Iterator; 38 import java.util.Locale; 39 import java.util.Map; 40 import java.util.Map.Entry; 41 import java.util.Set; 42 43 44 public class AttributedStringTest { 45 46 private static final String text = "Hello, world!"; 47 private static final Annotation hi = new Annotation("hi"); 48 private static final int[] array5_13 = {5, 13}; 49 private static final int[] array3_9_13 = {3, 9, 13}; 50 private static final int[] array5_9_13 = {5, 9, 13}; 51 private static final int[] array3_5_9_13 = {3, 5, 9, 13}; 52 private static final Attribute[] arrayLanguage = {Attribute.LANGUAGE}; 53 private static final Attribute[] arrayLanguageReading = {Attribute.LANGUAGE, Attribute.READING}; 54 private static final Set setLanguageReading = new HashSet(); 55 static { 56 setLanguageReading.add(Attribute.LANGUAGE); 57 setLanguageReading.add(Attribute.READING); 58 } 59 60 main(String argv[])61 public static final void main(String argv[]) throws Exception { 62 63 64 AttributedString string; 65 AttributedCharacterIterator iterator; 66 67 // create a string with text, but no attributes 68 string = new AttributedString(text); 69 iterator = string.getIterator(); 70 71 // make sure the text is there and attributes aren't 72 checkIteratorText(iterator, text); 73 if (!iterator.getAllAttributeKeys().isEmpty()) { 74 throwException(iterator, "iterator provides attributes where none are defined"); 75 } 76 77 // add an attribute to a subrange 78 string.addAttribute(Attribute.LANGUAGE, Locale.ENGLISH, 3, 9); 79 iterator = string.getIterator(); 80 81 // make sure the attribute is defined, and it's on the correct subrange 82 checkIteratorAttributeKeys(iterator, arrayLanguage); 83 checkIteratorSubranges(iterator, array3_9_13); 84 checkIteratorAttribute(iterator, 0, Attribute.LANGUAGE, null); 85 checkIteratorAttribute(iterator, 3, Attribute.LANGUAGE, Locale.ENGLISH); 86 checkIteratorAttribute(iterator, 9, Attribute.LANGUAGE, null); 87 88 // add an attribute to a subrange 89 string.addAttribute(Attribute.READING, hi, 0, 5); 90 iterator = string.getIterator(); 91 92 // make sure the attribute is defined, and it's on the correct subrange 93 checkIteratorAttributeKeys(iterator, arrayLanguageReading); 94 checkIteratorSubranges(iterator, array3_5_9_13); 95 checkIteratorAttribute(iterator, 0, Attribute.READING, hi); 96 checkIteratorAttribute(iterator, 3, Attribute.READING, hi); 97 checkIteratorAttribute(iterator, 5, Attribute.READING, null); 98 checkIteratorAttribute(iterator, 9, Attribute.READING, null); 99 100 // make sure the first attribute wasn't adversely affected 101 // in particular, we shouldn't see separate subranges (3,5) and (5,9). 102 checkIteratorSubranges(iterator, Attribute.LANGUAGE, array3_9_13); 103 checkIteratorAttribute(iterator, 0, Attribute.LANGUAGE, null); 104 checkIteratorAttribute(iterator, 3, Attribute.LANGUAGE, Locale.ENGLISH); 105 checkIteratorAttribute(iterator, 5, Attribute.LANGUAGE, Locale.ENGLISH); 106 checkIteratorAttribute(iterator, 9, Attribute.LANGUAGE, null); 107 108 // for the entire set of attributes, we expect four subranges 109 checkIteratorSubranges(iterator, setLanguageReading, array3_5_9_13); 110 111 // redefine the language attribute so that both language and reading are continuous from 0 to 5 112 string.addAttribute(Attribute.LANGUAGE, Locale.US, 0, 5); 113 iterator = string.getIterator(); 114 115 // make sure attributes got changed and merged correctly 116 checkIteratorAttributeKeys(iterator, arrayLanguageReading); 117 checkIteratorSubranges(iterator, array3_5_9_13); 118 checkIteratorSubranges(iterator, Attribute.LANGUAGE, array5_9_13); 119 checkIteratorSubranges(iterator, Attribute.READING, array5_13); 120 checkIteratorSubranges(iterator, setLanguageReading, array5_9_13); 121 checkIteratorAttribute(iterator, 0, Attribute.LANGUAGE, Locale.US); 122 checkIteratorAttribute(iterator, 3, Attribute.LANGUAGE, Locale.US); 123 checkIteratorAttribute(iterator, 5, Attribute.LANGUAGE, Locale.ENGLISH); 124 checkIteratorAttribute(iterator, 9, Attribute.LANGUAGE, null); 125 126 // make sure an annotation is only returned if its range is contained in the iterator's range 127 iterator = string.getIterator(null, 3, 5); 128 checkIteratorAttribute(iterator, 3, Attribute.READING, null); 129 checkIteratorAttribute(iterator, 5, Attribute.READING, null); 130 iterator = string.getIterator(null, 0, 4); 131 checkIteratorAttribute(iterator, 0, Attribute.READING, null); 132 checkIteratorAttribute(iterator, 3, Attribute.READING, null); 133 iterator = string.getIterator(null, 0, 5); 134 checkIteratorAttribute(iterator, 0, Attribute.READING, hi); 135 checkIteratorAttribute(iterator, 4, Attribute.READING, hi); 136 checkIteratorAttribute(iterator, 5, Attribute.READING, null); 137 138 } 139 checkIteratorText(AttributedCharacterIterator iterator, String expectedText)140 private static final void checkIteratorText(AttributedCharacterIterator iterator, String expectedText) throws Exception { 141 if (iterator.getEndIndex() - iterator.getBeginIndex() != expectedText.length()) { 142 throwException(iterator, "text length doesn't match between original text and iterator"); 143 } 144 145 char c = iterator.first(); 146 for (int i = 0; i < expectedText.length(); i++) { 147 if (c != expectedText.charAt(i)) { 148 throwException(iterator, "text content doesn't match between original text and iterator"); 149 } 150 c = iterator.next(); 151 } 152 if (c != CharacterIterator.DONE) { 153 throwException(iterator, "iterator text doesn't end with DONE"); 154 } 155 } 156 checkIteratorAttributeKeys(AttributedCharacterIterator iterator, Attribute[] expectedKeys)157 private static final void checkIteratorAttributeKeys(AttributedCharacterIterator iterator, Attribute[] expectedKeys) throws Exception { 158 Set iteratorKeys = iterator.getAllAttributeKeys(); 159 if (iteratorKeys.size() != expectedKeys.length) { 160 throwException(iterator, "number of keys returned by iterator doesn't match expectation"); 161 } 162 for (int i = 0; i < expectedKeys.length; i++) { 163 if (!iteratorKeys.contains(expectedKeys[i])) { 164 throwException(iterator, "expected key wasn't found in iterator's key set"); 165 } 166 } 167 } 168 checkIteratorSubranges(AttributedCharacterIterator iterator, int[] expectedLimits)169 private static final void checkIteratorSubranges(AttributedCharacterIterator iterator, int[] expectedLimits) throws Exception { 170 int previous = 0; 171 char c = iterator.first(); 172 for (int i = 0; i < expectedLimits.length; i++) { 173 if (iterator.getRunStart() != previous || iterator.getRunLimit() != expectedLimits[i]) { 174 throwException(iterator, "run boundaries are not as expected: " + iterator.getRunStart() + ", " + iterator.getRunLimit()); 175 } 176 previous = expectedLimits[i]; 177 c = iterator.setIndex(previous); 178 } 179 if (c != CharacterIterator.DONE) { 180 throwException(iterator, "iterator's run sequence doesn't end with DONE"); 181 } 182 } 183 checkIteratorSubranges(AttributedCharacterIterator iterator, Attribute key, int[] expectedLimits)184 private static final void checkIteratorSubranges(AttributedCharacterIterator iterator, Attribute key, int[] expectedLimits) throws Exception { 185 int previous = 0; 186 char c = iterator.first(); 187 for (int i = 0; i < expectedLimits.length; i++) { 188 if (iterator.getRunStart(key) != previous || iterator.getRunLimit(key) != expectedLimits[i]) { 189 throwException(iterator, "run boundaries are not as expected: " + iterator.getRunStart(key) + ", " + iterator.getRunLimit(key) + " for key " + key); 190 } 191 previous = expectedLimits[i]; 192 c = iterator.setIndex(previous); 193 } 194 if (c != CharacterIterator.DONE) { 195 throwException(iterator, "iterator's run sequence doesn't end with DONE"); 196 } 197 } 198 checkIteratorSubranges(AttributedCharacterIterator iterator, Set keys, int[] expectedLimits)199 private static final void checkIteratorSubranges(AttributedCharacterIterator iterator, Set keys, int[] expectedLimits) throws Exception { 200 int previous = 0; 201 char c = iterator.first(); 202 for (int i = 0; i < expectedLimits.length; i++) { 203 if (iterator.getRunStart(keys) != previous || iterator.getRunLimit(keys) != expectedLimits[i]) { 204 throwException(iterator, "run boundaries are not as expected: " + iterator.getRunStart(keys) + ", " + iterator.getRunLimit(keys) + " for keys " + keys); 205 } 206 previous = expectedLimits[i]; 207 c = iterator.setIndex(previous); 208 } 209 if (c != CharacterIterator.DONE) { 210 throwException(iterator, "iterator's run sequence doesn't end with DONE"); 211 } 212 } 213 checkIteratorAttribute(AttributedCharacterIterator iterator, int index, Attribute key, Object expectedValue)214 private static final void checkIteratorAttribute(AttributedCharacterIterator iterator, int index, Attribute key, Object expectedValue) throws Exception { 215 iterator.setIndex(index); 216 Object value = iterator.getAttribute(key); 217 if (!((expectedValue == null && value == null) || (expectedValue != null && expectedValue.equals(value)))) { 218 throwException(iterator, "iterator returns wrong attribute value - " + value + " instead of " + expectedValue); 219 } 220 value = iterator.getAttributes().get(key); 221 if (!((expectedValue == null && value == null) || (expectedValue != null && expectedValue.equals(value)))) { 222 throwException(iterator, "iterator's map returns wrong attribute value - " + value + " instead of " + expectedValue); 223 } 224 } 225 throwException(AttributedCharacterIterator iterator, String details)226 private static final void throwException(AttributedCharacterIterator iterator, String details) throws Exception { 227 dumpIterator(iterator); 228 throw new Exception(details); 229 } 230 dumpIterator(AttributedCharacterIterator iterator)231 private static final void dumpIterator(AttributedCharacterIterator iterator) { 232 Set attributeKeys = iterator.getAllAttributeKeys(); 233 System.out.print("All attributes: "); 234 Iterator keyIterator = attributeKeys.iterator(); 235 while (keyIterator.hasNext()) { 236 Attribute key = (Attribute) keyIterator.next(); 237 System.out.print(key); 238 } 239 for(char c = iterator.first(); c != CharacterIterator.DONE; c = iterator.next()) { 240 if (iterator.getIndex() == iterator.getBeginIndex() || 241 iterator.getIndex() == iterator.getRunStart()) { 242 System.out.println(); 243 Map attributes = iterator.getAttributes(); 244 Set entries = attributes.entrySet(); 245 Iterator attributeIterator = entries.iterator(); 246 while (attributeIterator.hasNext()) { 247 Map.Entry entry = (Map.Entry) attributeIterator.next(); 248 System.out.print("<" + entry.getKey() + ": " 249 + entry.getValue() + ">"); 250 } 251 } 252 System.out.print(" "); 253 System.out.print(c); 254 } 255 System.out.println(); 256 System.out.println("done"); 257 System.out.println(); 258 } 259 260 } 261