GNU Classpath (0.95) | |
Frames | No Frames |
1: /* AttributedString.java -- Models text with attributes 2: Copyright (C) 1998, 1999, 2004, 2005, 2006, 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: * @since 1.2 55: * 56: * @author Aaron M. Renn (arenn@urbanophile.com) 57: * @since 1.2 58: */ 59: public class AttributedString 60: { 61: 62: /** 63: * The attributes and ranges of text over which those attributes apply. 64: */ 65: final class AttributeRange 66: { 67: 68: /** A Map of the attributes */ 69: Map attribs; 70: 71: /** The beginning index of the attributes */ 72: int beginIndex; 73: 74: /** The ending index of the attributes */ 75: int endIndex; 76: 77: /** 78: * Creates a new attribute range. 79: * 80: * @param attribs the attributes. 81: * @param beginIndex the start index. 82: * @param endIndex the end index. 83: */ 84: AttributeRange(Map attribs, int beginIndex, int endIndex) 85: { 86: this.attribs = attribs; 87: this.beginIndex = beginIndex; 88: this.endIndex = endIndex; 89: } 90: 91: } // Inner class AttributeRange 92: 93: /** The string we are representing. */ 94: private StringCharacterIterator sci; 95: 96: /** The attribute information */ 97: private AttributeRange[] attribs; 98: 99: /** 100: * Creates a new instance of <code>AttributedString</code> 101: * that represents the specified <code>String</code> with no attributes. 102: * 103: * @param str The <code>String</code> to be attributed (<code>null</code> not 104: * permitted). 105: * 106: * @throws NullPointerException if <code>str</code> is <code>null</code>. 107: */ 108: public AttributedString(String str) 109: { 110: sci = new StringCharacterIterator(str); 111: attribs = new AttributeRange[0]; 112: } 113: 114: /** 115: * Creates a new instance of <code>AttributedString</code> 116: * that represents that specified <code>String</code> with the specified 117: * attributes over the entire length of the <code>String</code>. 118: * 119: * @param str The <code>String</code> to be attributed. 120: * @param attributes The attribute list. 121: */ 122: public AttributedString(String str, 123: Map<? extends AttributedCharacterIterator.Attribute, ?> attributes) 124: { 125: this(str); 126: 127: attribs = new AttributeRange[1]; 128: attribs[0] = new AttributeRange(attributes, 0, str.length()); 129: } 130: 131: /** 132: * Initializes a new instance of <code>AttributedString</code> 133: * that will use the text and attribute information from the specified 134: * <code>AttributedCharacterIterator</code>. 135: * 136: * @param aci The <code>AttributedCharacterIterator</code> containing the 137: * text and attribute information (<code>null</code> not 138: * permitted). 139: * 140: * @throws NullPointerException if <code>aci</code> is <code>null</code>. 141: */ 142: public AttributedString(AttributedCharacterIterator aci) 143: { 144: this(aci, aci.getBeginIndex(), aci.getEndIndex(), null); 145: } 146: 147: /** 148: * Initializes a new instance of <code>AttributedString</code> 149: * that will use the text and attribute information from the specified 150: * subrange of the specified <code>AttributedCharacterIterator</code>. 151: * 152: * @param aci The <code>AttributedCharacterIterator</code> containing the 153: * text and attribute information. 154: * @param beginIndex The beginning index of the text subrange. 155: * @param endIndex The ending index of the text subrange. 156: */ 157: public AttributedString(AttributedCharacterIterator aci, int beginIndex, 158: int endIndex) 159: { 160: this(aci, beginIndex, endIndex, null); 161: } 162: 163: /** 164: * Initializes a new instance of <code>AttributedString</code> 165: * that will use the text and attribute information from the specified 166: * subrange of the specified <code>AttributedCharacterIterator</code>. 167: * Only attributes from the source iterator that are present in the 168: * specified array of attributes will be included in the attribute list 169: * for this object. 170: * 171: * @param aci The <code>AttributedCharacterIterator</code> containing the 172: * text and attribute information. 173: * @param begin The beginning index of the text subrange. 174: * @param end The ending index of the text subrange. 175: * @param attributes A list of attributes to include from the iterator, or 176: * <code>null</code> to include all attributes. 177: */ 178: public AttributedString(AttributedCharacterIterator aci, int begin, int end, 179: AttributedCharacterIterator.Attribute[] attributes) 180: { 181: // Validate some arguments 182: if ((begin < 0) || (end < begin) || end > aci.getEndIndex()) 183: throw new IllegalArgumentException("Bad index values"); 184: 185: StringBuffer sb = new StringBuffer(""); 186: 187: // Get the valid attribute list 188: Set allAttribs = aci.getAllAttributeKeys(); 189: if (attributes != null) 190: allAttribs.retainAll(Arrays.asList(attributes)); 191: 192: // Loop through and extract the attributes 193: char c = aci.setIndex(begin); 194: 195: ArrayList accum = new ArrayList(); 196: do 197: { 198: sb.append(c); 199: 200: Iterator iter = allAttribs.iterator(); 201: while(iter.hasNext()) 202: { 203: Object obj = iter.next(); 204: 205: // What should we do if this is not true? 206: if (!(obj instanceof AttributedCharacterIterator.Attribute)) 207: continue; 208: 209: AttributedCharacterIterator.Attribute attrib = 210: (AttributedCharacterIterator.Attribute)obj; 211: 212: // Make sure the attribute is defined. 213: Object attribObj = aci.getAttribute(attrib); 214: if (attribObj == null) 215: continue; 216: int rl = aci.getRunLimit(attrib); 217: if (rl > end) 218: rl = end; 219: rl -= begin; 220: 221: // Check to see if we already processed this one 222: int rs = aci.getRunStart(attrib); 223: if ((rs < aci.getIndex()) && (aci.getIndex() != begin)) 224: continue; 225: 226: // If the attribute run starts before the beginning index, we 227: // need to junk it if it is an Annotation. 228: rs -= begin; 229: if (rs < 0) 230: { 231: if (attribObj instanceof Annotation) 232: continue; 233: 234: rs = 0; 235: } 236: 237: // Create a map object. Yes this will only contain one attribute 238: Map newMap = new Hashtable(); 239: newMap.put(attrib, attribObj); 240: 241: // Add it to the attribute list. 242: accum.add(new AttributeRange(newMap, rs, rl)); 243: } 244: 245: c = aci.next(); 246: } 247: while( aci.getIndex() < end ); 248: 249: attribs = new AttributeRange[accum.size()]; 250: attribs = (AttributeRange[]) accum.toArray(attribs); 251: 252: sci = new StringCharacterIterator(sb.toString()); 253: } 254: 255: /** 256: * Adds a new attribute that will cover the entire string. 257: * 258: * @param attrib The attribute to add. 259: * @param value The value of the attribute. 260: */ 261: public void addAttribute(AttributedCharacterIterator.Attribute attrib, 262: Object value) 263: { 264: addAttribute(attrib, value, 0, sci.getEndIndex()); 265: } 266: 267: /** 268: * Adds a new attribute that will cover the specified subrange 269: * of the string. 270: * 271: * @param attrib The attribute to add. 272: * @param value The value of the attribute, which may be <code>null</code>. 273: * @param begin The beginning index of the subrange. 274: * @param end The ending index of the subrange. 275: * 276: * @exception IllegalArgumentException If attribute is <code>null</code> or 277: * the subrange is not valid. 278: */ 279: public void addAttribute(AttributedCharacterIterator.Attribute attrib, 280: Object value, int begin, int end) 281: { 282: if (attrib == null) 283: throw new IllegalArgumentException("null attribute"); 284: if (end <= begin) 285: throw new IllegalArgumentException("Requires end > begin"); 286: HashMap hm = new HashMap(); 287: hm.put(attrib, value); 288: 289: addAttributes(hm, begin, end); 290: } 291: 292: /** 293: * Adds all of the attributes in the specified list to the 294: * specified subrange of the string. 295: * 296: * @param attributes The list of attributes. 297: * @param beginIndex The beginning index. 298: * @param endIndex The ending index 299: * 300: * @throws NullPointerException if <code>attributes</code> is 301: * <code>null</code>. 302: * @throws IllegalArgumentException if the subrange is not valid. 303: */ 304: public void addAttributes(Map<? extends AttributedCharacterIterator.Attribute, ?> attributes, 305: int beginIndex, int endIndex) 306: { 307: if (attributes == null) 308: throw new NullPointerException("null attribute"); 309: 310: if ((beginIndex < 0) || (endIndex > sci.getEndIndex()) || 311: (endIndex <= beginIndex)) 312: throw new IllegalArgumentException("bad range"); 313: 314: AttributeRange[] new_list = new AttributeRange[attribs.length + 1]; 315: System.arraycopy(attribs, 0, new_list, 0, attribs.length); 316: attribs = new_list; 317: attribs[attribs.length - 1] = new AttributeRange(attributes, beginIndex, 318: endIndex); 319: } 320: 321: /** 322: * Returns an <code>AttributedCharacterIterator</code> that 323: * will iterate over the entire string. 324: * 325: * @return An <code>AttributedCharacterIterator</code> for the entire string. 326: */ 327: public AttributedCharacterIterator getIterator() 328: { 329: return(new AttributedStringIterator(sci, attribs, 0, sci.getEndIndex(), 330: null)); 331: } 332: 333: /** 334: * Returns an <code>AttributedCharacterIterator</code> that 335: * will iterate over the entire string. This iterator will return information 336: * about the list of attributes in the specified array. Attributes not in 337: * the array may or may not be returned by the iterator. If the specified 338: * array is <code>null</code>, all attributes will be returned. 339: * 340: * @param attributes A list of attributes to include in the returned iterator. 341: * 342: * @return An <code>AttributedCharacterIterator</code> for this string. 343: */ 344: public AttributedCharacterIterator getIterator( 345: AttributedCharacterIterator.Attribute[] attributes) 346: { 347: return(getIterator(attributes, 0, sci.getEndIndex())); 348: } 349: 350: /** 351: * Returns an <code>AttributedCharacterIterator</code> that 352: * will iterate over the specified subrange. This iterator will return 353: * information about the list of attributes in the specified array. 354: * Attributes not in the array may or may not be returned by the iterator. 355: * If the specified array is <code>null</code>, all attributes will be 356: * returned. 357: * 358: * @param attributes A list of attributes to include in the returned iterator. 359: * @param beginIndex The beginning index of the subrange. 360: * @param endIndex The ending index of the subrange. 361: * 362: * @return An <code>AttributedCharacterIterator</code> for this string. 363: */ 364: public AttributedCharacterIterator getIterator( 365: AttributedCharacterIterator.Attribute[] attributes, 366: int beginIndex, int endIndex) 367: { 368: if ((beginIndex < 0) || (endIndex > sci.getEndIndex()) || 369: (endIndex < beginIndex)) 370: throw new IllegalArgumentException("bad range"); 371: 372: return(new AttributedStringIterator(sci, attribs, beginIndex, endIndex, 373: attributes)); 374: } 375: 376: } // class AttributedString
GNU Classpath (0.95) |