GNU Classpath (0.20) | |
Frames | No Frames |
1: /* AttributedString.java -- Models text with attributes 2: Copyright (C) 1998, 1999, 2004, 2005 Free Software Foundation, Inc. 3: 4: This file is part of GNU Classpath. 5: 6: GNU Classpath is free software; you can redistribute it and/or modify 7: it under the terms of the GNU General Public License as published by 8: the Free Software Foundation; either version 2, or (at your option) 9: any later version. 10: 11: GNU Classpath is distributed in the hope that it will be useful, but 12: WITHOUT ANY WARRANTY; without even the implied warranty of 13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14: General Public License for more details. 15: 16: You should have received a copy of the GNU General Public License 17: along with GNU Classpath; see the file COPYING. If not, write to the 18: Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 19: 02110-1301 USA. 20: 21: Linking this library statically or dynamically with other modules is 22: making a combined work based on this library. Thus, the terms and 23: conditions of the GNU General Public License cover the whole 24: combination. 25: 26: As a special exception, the copyright holders of this library give you 27: permission to link this library with independent modules to produce an 28: executable, regardless of the license terms of these independent 29: modules, and to copy and distribute the resulting executable under 30: terms of your choice, provided that you also meet, for each linked 31: independent module, the terms and conditions of the license of that 32: module. An independent module is a module which is not derived from 33: or based on this library. If you modify this library, you may extend 34: this exception to your version of the library, but you are not 35: obligated to do so. If you do not wish to do so, delete this 36: exception statement from your version. */ 37: 38: 39: package java.text; 40: 41: import java.util.ArrayList; 42: import java.util.Arrays; 43: import java.util.HashMap; 44: import java.util.Hashtable; 45: import java.util.Iterator; 46: import java.util.Map; 47: import java.util.Set; 48: 49: /** 50: * This class models a <code>String</code> with attributes over various 51: * subranges of the string. It allows applications to access this 52: * information via the <code>AttributedCharacterIterator</code> interface. 53: * 54: * @author Aaron M. Renn (arenn@urbanophile.com) 55: */ 56: public class AttributedString 57: { 58: 59: /** 60: * The attributes and ranges of text over which those attributes apply. 61: */ 62: final class AttributeRange 63: { 64: 65: /** A Map of the attributes */ 66: Map attribs; 67: 68: /** The beginning index of the attributes */ 69: int begin_index; 70: 71: /** The ending index of the attributes */ 72: int end_index; 73: 74: /** 75: * Creates a new attribute range. 76: * 77: * @param attribs the attributes. 78: * @param begin_index the start index. 79: * @param end_index the end index. 80: */ 81: AttributeRange(Map attribs, int begin_index, int end_index) 82: { 83: this.attribs = attribs; 84: this.begin_index = begin_index; 85: this.end_index = end_index; 86: } 87: 88: } // Inner class AttributeRange 89: 90: /** The string we are representing. */ 91: private StringCharacterIterator sci; 92: 93: /** The attribute information */ 94: private AttributeRange[] attribs; 95: 96: /** 97: * Creates a new instance of <code>AttributedString</code> 98: * that represents the specified <code>String</code> with no attributes. 99: * 100: * @param str The <code>String</code> to be attributed (<code>null</code> not 101: * permitted). 102: * 103: * @throws NullPointerException if <code>str</code> is <code>null</code>. 104: */ 105: public AttributedString(String str) 106: { 107: sci = new StringCharacterIterator(str); 108: attribs = new AttributeRange[0]; 109: } 110: 111: /** 112: * Creates a new instance of <code>AttributedString</code> 113: * that represents that specified <code>String</code> with the specified 114: * attributes over the entire length of the <code>String</code>. 115: * 116: * @param str The <code>String</code> to be attributed. 117: * @param attributes The attribute list. 118: */ 119: public AttributedString(String str, Map attributes) 120: { 121: this(str); 122: 123: attribs = new AttributeRange[1]; 124: attribs[0] = new AttributeRange(attributes, 0, str.length()); 125: } 126: 127: /** 128: * Initializes a new instance of <code>AttributedString</code> 129: * that will use the text and attribute information from the specified 130: * <code>AttributedCharacterIterator</code>. 131: * 132: * @param aci The <code>AttributedCharacterIterator</code> containing the 133: * text and attribute information (<code>null</code> not 134: * permitted). 135: * 136: * @throws NullPointerException if <code>aci</code> is <code>null</code>. 137: */ 138: public AttributedString(AttributedCharacterIterator aci) 139: { 140: this(aci, aci.getBeginIndex(), aci.getEndIndex(), null); 141: } 142: 143: /** 144: * Initializes a new instance of <code>AttributedString</code> 145: * that will use the text and attribute information from the specified 146: * subrange of the specified <code>AttributedCharacterIterator</code>. 147: * 148: * @param aci The <code>AttributedCharacterIterator</code> containing the 149: * text and attribute information. 150: * @param begin_index The beginning index of the text subrange. 151: * @param end_index The ending index of the text subrange. 152: */ 153: public AttributedString(AttributedCharacterIterator aci, int begin_index, 154: int end_index) 155: { 156: this(aci, begin_index, end_index, null); 157: } 158: 159: /** 160: * Initializes a new instance of <code>AttributedString</code> 161: * that will use the text and attribute information from the specified 162: * subrange of the specified <code>AttributedCharacterIterator</code>. 163: * Only attributes from the source iterator that are present in the 164: * specified array of attributes will be included in the attribute list 165: * for this object. 166: * 167: * @param aci The <code>AttributedCharacterIterator</code> containing the 168: * text and attribute information. 169: * @param begin The beginning index of the text subrange. 170: * @param end The ending index of the text subrange. 171: * @param attributes A list of attributes to include from the iterator, or 172: * <code>null</code> to include all attributes. 173: */ 174: public AttributedString(AttributedCharacterIterator aci, int begin, int end, 175: AttributedCharacterIterator.Attribute[] attributes) 176: { 177: // Validate some arguments 178: if ((begin < 0) || (end < begin) || end > aci.getEndIndex()) 179: throw new IllegalArgumentException("Bad index values"); 180: 181: StringBuffer sb = new StringBuffer(""); 182: 183: // Get the valid attribute list 184: Set all_attribs = aci.getAllAttributeKeys(); 185: if (attributes != null) 186: all_attribs.retainAll(Arrays.asList(attributes)); 187: 188: // Loop through and extract the attributes 189: char c = aci.setIndex(begin); 190: 191: ArrayList accum = new ArrayList(); 192: do 193: { 194: sb.append(c); 195: 196: Iterator iter = all_attribs.iterator(); 197: while(iter.hasNext()) 198: { 199: Object obj = iter.next(); 200: 201: // What should we do if this is not true? 202: if (!(obj instanceof AttributedCharacterIterator.Attribute)) 203: continue; 204: 205: AttributedCharacterIterator.Attribute attrib = 206: (AttributedCharacterIterator.Attribute)obj; 207: 208: // Make sure the attribute is defined. 209: int rl = aci.getRunLimit(attrib); 210: if (rl == -1) 211: continue; 212: if (rl > end) 213: rl = end; 214: rl -= begin; 215: 216: // Check to see if we already processed this one 217: int rs = aci.getRunStart(attrib); 218: if ((rs < aci.getIndex()) && (aci.getIndex() != begin)) 219: continue; 220: 221: // If the attribute run starts before the beginning index, we 222: // need to junk it if it is an Annotation. 223: Object attrib_obj = aci.getAttribute(attrib); 224: if (rs < begin) 225: { 226: if (attrib_obj instanceof Annotation) 227: continue; 228: 229: rs = begin; 230: } 231: else 232: { 233: rs -= begin; 234: } 235: 236: // Create a map object. Yes this will only contain one attribute 237: Map new_map = new Hashtable(); 238: new_map.put(attrib, attrib_obj); 239: 240: // Add it to the attribute list. 241: accum.add(new AttributeRange(new_map, rs, rl)); 242: } 243: 244: c = aci.next(); 245: } 246: while(c != CharacterIterator.DONE); 247: 248: attribs = new AttributeRange[accum.size()]; 249: attribs = (AttributeRange[]) accum.toArray(attribs); 250: 251: sci = new StringCharacterIterator(sb.toString()); 252: } 253: 254: /** 255: * Adds a new attribute that will cover the entire string. 256: * 257: * @param attrib The attribute to add. 258: * @param value The value of the attribute. 259: */ 260: public void addAttribute(AttributedCharacterIterator.Attribute attrib, 261: Object value) 262: { 263: addAttribute(attrib, value, 0, sci.getEndIndex()); 264: } 265: 266: /** 267: * Adds a new attribute that will cover the specified subrange 268: * of the string. 269: * 270: * @param attrib The attribute to add. 271: * @param value The value of the attribute, which may be <code>null</code>. 272: * @param begin The beginning index of the subrange. 273: * @param end The ending index of the subrange. 274: * 275: * @exception IllegalArgumentException If attribute is <code>null</code> or 276: * the subrange is not valid. 277: */ 278: public void addAttribute(AttributedCharacterIterator.Attribute attrib, 279: Object value, int begin, int end) 280: { 281: if (attrib == null) 282: throw new IllegalArgumentException("null attribute"); 283: if (end <= begin) 284: throw new IllegalArgumentException("Requires end > begin"); 285: HashMap hm = new HashMap(); 286: hm.put(attrib, value); 287: 288: addAttributes(hm, begin, end); 289: } 290: 291: /** 292: * Adds all of the attributes in the specified list to the 293: * specified subrange of the string. 294: * 295: * @param attributes The list of attributes. 296: * @param begin_index The beginning index. 297: * @param end_index The ending index 298: * 299: * @throws NullPointerException if <code>attributes</code> is 300: * <code>null</code>. 301: * @throws IllegalArgumentException if the subrange is not valid. 302: */ 303: public void addAttributes(Map attributes, int begin_index, int end_index) 304: { 305: if (attributes == null) 306: throw new NullPointerException("null attribute"); 307: 308: if ((begin_index < 0) || (end_index > sci.getEndIndex()) || 309: (end_index <= begin_index)) 310: throw new IllegalArgumentException("bad range"); 311: 312: AttributeRange[] new_list = new AttributeRange[attribs.length + 1]; 313: System.arraycopy(attribs, 0, new_list, 0, attribs.length); 314: attribs = new_list; 315: attribs[attribs.length - 1] = new AttributeRange(attributes, begin_index, 316: end_index); 317: } 318: 319: /** 320: * Returns an <code>AttributedCharacterIterator</code> that 321: * will iterate over the entire string. 322: * 323: * @return An <code>AttributedCharacterIterator</code> for the entire string. 324: */ 325: public AttributedCharacterIterator getIterator() 326: { 327: return(new AttributedStringIterator(sci, attribs, 0, sci.getEndIndex(), 328: null)); 329: } 330: 331: /** 332: * Returns an <code>AttributedCharacterIterator</code> that 333: * will iterate over the entire string. This iterator will return information 334: * about the list of attributes in the specified array. Attributes not in 335: * the array may or may not be returned by the iterator. If the specified 336: * array is <code>null</code>, all attributes will be returned. 337: * 338: * @param attributes A list of attributes to include in the returned iterator. 339: * 340: * @return An <code>AttributedCharacterIterator</code> for this string. 341: */ 342: public AttributedCharacterIterator getIterator( 343: AttributedCharacterIterator.Attribute[] attributes) 344: { 345: return(getIterator(attributes, 0, sci.getEndIndex())); 346: } 347: 348: /** 349: * Returns an <code>AttributedCharacterIterator</code> that 350: * will iterate over the specified subrange. This iterator will return 351: * information about the list of attributes in the specified array. 352: * Attributes not in the array may or may not be returned by the iterator. 353: * If the specified array is <code>null</code>, all attributes will be 354: * returned. 355: * 356: * @param attributes A list of attributes to include in the returned iterator. 357: * @param begin_index The beginning index of the subrange. 358: * @param end_index The ending index of the subrange. 359: * 360: * @return An <code>AttributedCharacterIterator</code> for this string. 361: */ 362: public AttributedCharacterIterator getIterator( 363: AttributedCharacterIterator.Attribute[] attributes, 364: int begin_index, int end_index) 365: { 366: if ((begin_index < 0) || (end_index > sci.getEndIndex()) || 367: (end_index < begin_index)) 368: throw new IllegalArgumentException("bad range"); 369: 370: return(new AttributedStringIterator(sci, attribs, begin_index, end_index, 371: attributes)); 372: } 373: 374: } // class AttributedString
GNU Classpath (0.20) |