| /* AttributedString.java -- Models text with attributes | |
| Copyright (C) 1998, 1999 Free Software Foundation, Inc. | |
| This file is part of GNU Classpath. | |
| GNU Classpath is free software; you can redistribute it and/or modify | |
| it under the terms of the GNU General Public License as published by | |
| the Free Software Foundation; either version 2, or (at your option) | |
| any later version. | |
| GNU Classpath is distributed in the hope that it will be useful, but | |
| WITHOUT ANY WARRANTY; without even the implied warranty of | |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
| General Public License for more details. | |
| You should have received a copy of the GNU General Public License | |
| along with GNU Classpath; see the file COPYING. If not, write to the | |
| Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA | |
| 02111-1307 USA. | |
| As a special exception, if you link this library with other files to | |
| produce an executable, this library does not by itself cause the | |
| resulting executable to be covered by the GNU General Public License. | |
| This exception does not however invalidate any other reasons why the | |
| executable file might be covered by the GNU General Public License. */ | |
| package java.text; | |
| import java.util.Iterator; | |
| import java.util.Hashtable; | |
| import java.util.HashSet; | |
| import java.util.Map; | |
| import java.util.Set; | |
| /** | |
| * This class models a <code>String</code> with attributes over various | |
| * subranges of the string. It allows applications to access this | |
| * information via the <code>AttributedCharcterIterator</code> interface. | |
| * | |
| * @version 0.0 | |
| * | |
| * @author Aaron M. Renn (arenn@urbanophile.com) | |
| */ | |
| public class AttributedString | |
| { | |
| /*************************************************************************/ | |
| /* | |
| * Inner Classes | |
| */ | |
| /** | |
| * This class contains the attributes and ranges of text over which | |
| * that attributes apply. | |
| */ | |
| final class AttributeRange | |
| { | |
| /* | |
| * Instance Variables | |
| */ | |
| /** | |
| * A Map of the attributes | |
| */ | |
| Map attribs; | |
| /** | |
| * The beginning index of the attributes | |
| */ | |
| int begin_index; | |
| /** | |
| * The ending index of the attributes | |
| */ | |
| int end_index; | |
| /*************************************************************************/ | |
| /* | |
| * Constructors | |
| */ | |
| AttributeRange(Map attribs, int begin_index, int end_index) | |
| { | |
| this.attribs = attribs; | |
| this.begin_index = begin_index; | |
| this.end_index = end_index; | |
| } | |
| } // Inner class AttributeRange | |
| /*************************************************************************/ | |
| /* | |
| * Instance Variables | |
| */ | |
| /** | |
| * This object holds the string we are representing. | |
| */ | |
| private StringCharacterIterator sci; | |
| /** | |
| * This is the attribute information | |
| */ | |
| private AttributeRange[] attribs; | |
| /*************************************************************************/ | |
| /* | |
| * Constructors | |
| */ | |
| /** | |
| * This method initializes a new instance of <code>AttributedString</code> | |
| * that represents the specified <code>String</code> with no attributes. | |
| * | |
| * @param str The <code>String</code> to be attributed. | |
| */ | |
| public | |
| AttributedString(String str) | |
| { | |
| sci = new StringCharacterIterator(str); | |
| attribs = new AttributeRange[0]; | |
| } | |
| /*************************************************************************/ | |
| /** | |
| * This method initializes a new instance of <code>AttributedString</code> | |
| * that represents that specified <code>String</code> with the specified | |
| * attributes over the entire length of the <code>String</code>. | |
| * | |
| * @param str The <code>String</code> to be attributed. | |
| * @param attributes The attribute list. | |
| */ | |
| public | |
| AttributedString(String str, Map attributes) | |
| { | |
| this(str); | |
| attribs = new AttributeRange[1]; | |
| attribs[0] = new AttributeRange(attributes, 0, str.length()); | |
| } | |
| /*************************************************************************/ | |
| /** | |
| * This method initializes a new instance of <code>AttributedString</code> | |
| * that will use the text and attribute information from the specified | |
| * <code>AttributedCharacterIterator</code>. | |
| * | |
| * @param aci The <code>AttributedCharacterIterator</code> containing the text and attribute information. | |
| */ | |
| public | |
| AttributedString(AttributedCharacterIterator aci) | |
| { | |
| this(aci, aci.getBeginIndex(), aci.getEndIndex(), null); | |
| } | |
| /*************************************************************************/ | |
| /** | |
| * This method initializes a new instance of <code>AttributedString</code> | |
| * that will use the text and attribute information from the specified | |
| * subrange of the specified <code>AttributedCharacterIterator</code>. | |
| * | |
| * @param aci The <code>AttributedCharacterIterator</code> containing the text and attribute information. | |
| * @param begin_index The beginning index of the text subrange. | |
| * @param end_index The ending index of the text subrange. | |
| */ | |
| public | |
| AttributedString(AttributedCharacterIterator aci, int begin_index, | |
| int end_index) | |
| { | |
| this(aci, begin_index, end_index, null); | |
| } | |
| /*************************************************************************/ | |
| /** | |
| * This method initializes a new instance of <code>AttributedString</code> | |
| * that will use the text and attribute information from the specified | |
| * subrange of the specified <code>AttributedCharacterIterator</code>. | |
| * Only attributes from the source iterator that are present in the | |
| * specified array of attributes will be included in the attribute list | |
| * for this object. | |
| * | |
| * @param aci The <code>AttributedCharacterIterator</code> containing the text and attribute information. | |
| * @param begin_index The beginning index of the text subrange. | |
| * @param end_index The ending index of the text subrange. | |
| * @param attributes A list of attributes to include from the iterator, or <code>null</code> to include all attributes. | |
| */ | |
| public | |
| AttributedString(AttributedCharacterIterator aci, int begin_index, | |
| int end_index, AttributedCharacterIterator.Attribute[] attributes) | |
| { | |
| // Validate some arguments | |
| if ((begin_index < 0) || (end_index < begin_index)) | |
| throw new IllegalArgumentException("Bad index values"); | |
| StringBuffer sb = new StringBuffer(""); | |
| // Get the valid attribute list | |
| Set all_attribs = aci.getAllAttributeKeys(); | |
| if (attributes != null) | |
| { | |
| Set valid_attribs = new HashSet(); | |
| Iterator iter = all_attribs.iterator(); | |
| while (iter.hasNext()) | |
| { | |
| Object obj = iter.next(); | |
| int i; | |
| for (i = 0; i < attributes.length; i++) | |
| if (obj.equals(attributes[0])) | |
| break; | |
| if (i == attributes.length) | |
| continue; | |
| valid_attribs.add(obj); | |
| } | |
| all_attribs = valid_attribs; | |
| } | |
| // Loop through and extract the attributes | |
| char c = aci.setIndex(begin_index); | |
| do | |
| { | |
| sb.append(c); | |
| Iterator iter = all_attribs.iterator(); | |
| while(iter.hasNext()) | |
| { | |
| Object obj = iter.next(); | |
| // What should we do if this is not true? | |
| if (!(obj instanceof AttributedCharacterIterator.Attribute)) | |
| continue; | |
| AttributedCharacterIterator.Attribute attrib = | |
| (AttributedCharacterIterator.Attribute)obj; | |
| // Make sure the attribute is defined. | |
| int rl = aci.getRunLimit(attrib); | |
| if (rl == -1) | |
| continue; | |
| if (rl > end_index) | |
| rl = end_index; | |
| rl -= begin_index; | |
| // Check to see if we already processed this one | |
| int rs = aci.getRunStart(attrib); | |
| if ((rs < aci.getIndex()) && (aci.getIndex() != begin_index)) | |
| continue; | |
| // If the attribute run starts before the beginning index, we | |
| // need to junk it if it is an Annotation. | |
| Object attrib_obj = aci.getAttribute(attrib); | |
| if (rs < begin_index) | |
| { | |
| if (attrib_obj instanceof Annotation) | |
| continue; | |
| rs = begin_index; | |
| } | |
| else | |
| { | |
| rs -= begin_index; | |
| } | |
| // Create a map object. Yes this will only contain one attribute | |
| Map new_map = new Hashtable(); | |
| new_map.put(attrib, attrib_obj); | |
| // Add it to the attribute list. Yes this is a bad way to do things. | |
| AttributeRange[] new_list = new AttributeRange[attribs.length + 1]; | |
| System.arraycopy(attribs, 0, new_list, 0, attribs.length); | |
| attribs = new_list; | |
| attribs[attribs.length - 1] = new AttributeRange(new_map, rs, rl); | |
| } | |
| c = aci.next(); | |
| } | |
| while(c != CharacterIterator.DONE); | |
| sci = new StringCharacterIterator(sb.toString()); | |
| } | |
| /*************************************************************************/ | |
| /* | |
| * Instance Methods | |
| */ | |
| /** | |
| * This method adds a new attribute that will cover the entire string. | |
| * | |
| * @param attrib The attribute to add. | |
| * @param value The value of the attribute. | |
| */ | |
| public void | |
| addAttribute(AttributedCharacterIterator.Attribute attrib, Object value) | |
| { | |
| addAttribute(attrib, value, 0, sci.getEndIndex() - 1); | |
| } | |
| /*************************************************************************/ | |
| /** | |
| * This method adds a new attribute that will cover the specified subrange | |
| * of the string. | |
| * | |
| * @param attrib The attribute to add. | |
| * @param value The value of the attribute. | |
| * @param begin_index The beginning index of the subrange. | |
| * @param end_index The ending index of the subrange. | |
| * | |
| * @exception IllegalArgumentException If attribute is <code>null</code> or the subrange is not valid. | |
| */ | |
| public void | |
| addAttribute(AttributedCharacterIterator.Attribute attrib, Object value, | |
| int begin_index, int end_index) | |
| { | |
| if (attrib == null) | |
| throw new IllegalArgumentException("null attribute"); | |
| Hashtable ht = new Hashtable(); | |
| ht.put(attrib, value); | |
| addAttributes(ht, begin_index, end_index); | |
| } | |
| /*************************************************************************/ | |
| /** | |
| * This method adds all of the attributes in the specified list to the | |
| * specified subrange of the string. | |
| * | |
| * @param attributes The list of attributes. | |
| * @param begin_index The beginning index. | |
| * @param end_index The ending index | |
| * | |
| * @param IllegalArgumentException If the list is <code>null</code> or the subrange is not valid. | |
| */ | |
| public void | |
| addAttributes(Map attributes, int begin_index, int end_index) | |
| { | |
| if (attributes == null) | |
| throw new IllegalArgumentException("null attribute"); | |
| if ((begin_index < 0) || (end_index > sci.getEndIndex()) || | |
| (end_index < begin_index)) | |
| throw new IllegalArgumentException("bad range"); | |
| AttributeRange[] new_list = new AttributeRange[attribs.length + 1]; | |
| System.arraycopy(attribs, 0, new_list, 0, attribs.length); | |
| attribs = new_list; | |
| attribs[attribs.length - 1] = new AttributeRange(attributes, begin_index, | |
| end_index); | |
| } | |
| /*************************************************************************/ | |
| /** | |
| * This method returns an <code>AttributedCharacterIterator</code> that | |
| * will iterate over the entire string. | |
| * | |
| * @return An <code>AttributedCharacterIterator</code> for the entire string. | |
| */ | |
| public AttributedCharacterIterator | |
| getIterator() | |
| { | |
| return(new AttributedStringIterator(sci, attribs, 0, sci.getEndIndex() - 1, | |
| null)); | |
| } | |
| /*************************************************************************/ | |
| /** | |
| * This method returns an <code>AttributedCharacterIterator</code> that | |
| * will iterate over the entire string. This iterator will return information | |
| * about the list of attributes in the specified array. Attributes not in | |
| * the array may or may not be returned by the iterator. If the specified | |
| * array is <code>null</code>, all attributes will be returned. | |
| * | |
| * @param attributes A list of attributes to include in the returned iterator. | |
| * | |
| * @return An <code>AttributedCharacterIterator</code> for this string. | |
| */ | |
| public AttributedCharacterIterator | |
| getIterator(AttributedCharacterIterator.Attribute[] attributes) | |
| { | |
| return(getIterator(attributes, 0, sci.getEndIndex() - 1)); | |
| } | |
| /*************************************************************************/ | |
| /** | |
| * This method returns an <code>AttributedCharacterIterator</code> that | |
| * will iterate over the specified subrange. This iterator will return information | |
| * about the list of attributes in the specified array. Attributes not in | |
| * the array may or may not be returned by the iterator. If the specified | |
| * array is <code>null</code>, all attributes will be returned. | |
| * | |
| * @param attributes A list of attributes to include in the returned iterator. | |
| * @param begin_index The beginning index of the subrange. | |
| * @param end_index The ending index of the subrange. | |
| * | |
| * @return An <code>AttributedCharacterIterator</code> for this string. | |
| */ | |
| public AttributedCharacterIterator | |
| getIterator(AttributedCharacterIterator.Attribute[] attributes, | |
| int begin_index, int end_index) | |
| { | |
| if ((begin_index < 0) || (end_index > sci.getEndIndex()) || | |
| (end_index < begin_index)) | |
| throw new IllegalArgumentException("bad range"); | |
| return(new AttributedStringIterator(sci, attribs, begin_index, end_index, | |
| attributes)); | |
| } | |
| } // class AttributedString | |