| /* AttributedString.java -- Models text with attributes | |
| Copyright (C) 1998, 1999, 2004, 2005 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., 51 Franklin Street, Fifth Floor, Boston, MA | |
| 02110-1301 USA. | |
| Linking this library statically or dynamically with other modules is | |
| making a combined work based on this library. Thus, the terms and | |
| conditions of the GNU General Public License cover the whole | |
| combination. | |
| As a special exception, the copyright holders of this library give you | |
| permission to link this library with independent modules to produce an | |
| executable, regardless of the license terms of these independent | |
| modules, and to copy and distribute the resulting executable under | |
| terms of your choice, provided that you also meet, for each linked | |
| independent module, the terms and conditions of the license of that | |
| module. An independent module is a module which is not derived from | |
| or based on this library. If you modify this library, you may extend | |
| this exception to your version of the library, but you are not | |
| obligated to do so. If you do not wish to do so, delete this | |
| exception statement from your version. */ | |
| package java.text; | |
| import java.util.ArrayList; | |
| import java.util.Arrays; | |
| import java.util.HashMap; | |
| import java.util.Hashtable; | |
| import java.util.Iterator; | |
| 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>AttributedCharacterIterator</code> interface. | |
| * | |
| * @author Aaron M. Renn (arenn@urbanophile.com) | |
| */ | |
| public class AttributedString | |
| { | |
| /** | |
| * The attributes and ranges of text over which those attributes apply. | |
| */ | |
| final class AttributeRange | |
| { | |
| /** 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; | |
| /** | |
| * Creates a new attribute range. | |
| * | |
| * @param attribs the attributes. | |
| * @param begin_index the start index. | |
| * @param end_index the end index. | |
| */ | |
| 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 | |
| /** The string we are representing. */ | |
| private StringCharacterIterator sci; | |
| /** The attribute information */ | |
| private AttributeRange[] attribs; | |
| /** | |
| * Creates 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 (<code>null</code> not | |
| * permitted). | |
| * | |
| * @throws NullPointerException if <code>str</code> is <code>null</code>. | |
| */ | |
| public AttributedString(String str) | |
| { | |
| sci = new StringCharacterIterator(str); | |
| attribs = new AttributeRange[0]; | |
| } | |
| /** | |
| * Creates 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()); | |
| } | |
| /** | |
| * 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 (<code>null</code> not | |
| * permitted). | |
| * | |
| * @throws NullPointerException if <code>aci</code> is <code>null</code>. | |
| */ | |
| public AttributedString(AttributedCharacterIterator aci) | |
| { | |
| this(aci, aci.getBeginIndex(), aci.getEndIndex(), null); | |
| } | |
| /** | |
| * 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); | |
| } | |
| /** | |
| * 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 The beginning index of the text subrange. | |
| * @param end 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, int end, | |
| AttributedCharacterIterator.Attribute[] attributes) | |
| { | |
| // Validate some arguments | |
| if ((begin < 0) || (end < begin) || end > aci.getEndIndex()) | |
| throw new IllegalArgumentException("Bad index values"); | |
| StringBuffer sb = new StringBuffer(""); | |
| // Get the valid attribute list | |
| Set all_attribs = aci.getAllAttributeKeys(); | |
| if (attributes != null) | |
| all_attribs.retainAll(Arrays.asList(attributes)); | |
| // Loop through and extract the attributes | |
| char c = aci.setIndex(begin); | |
| ArrayList accum = new ArrayList(); | |
| 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) | |
| rl = end; | |
| rl -= begin; | |
| // Check to see if we already processed this one | |
| int rs = aci.getRunStart(attrib); | |
| if ((rs < aci.getIndex()) && (aci.getIndex() != begin)) | |
| 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); | |
| rs -= begin; | |
| if (rs < 0) | |
| { | |
| if (attrib_obj instanceof Annotation) | |
| continue; | |
| rs = 0; | |
| } | |
| // 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. | |
| accum.add(new AttributeRange(new_map, rs, rl)); | |
| } | |
| c = aci.next(); | |
| } | |
| while( aci.getIndex() < end ); | |
| attribs = new AttributeRange[accum.size()]; | |
| attribs = (AttributeRange[]) accum.toArray(attribs); | |
| sci = new StringCharacterIterator(sb.toString()); | |
| } | |
| /** | |
| * 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()); | |
| } | |
| /** | |
| * 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, which may be <code>null</code>. | |
| * @param begin The beginning index of the subrange. | |
| * @param end 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, int end) | |
| { | |
| if (attrib == null) | |
| throw new IllegalArgumentException("null attribute"); | |
| if (end <= begin) | |
| throw new IllegalArgumentException("Requires end > begin"); | |
| HashMap hm = new HashMap(); | |
| hm.put(attrib, value); | |
| addAttributes(hm, begin, end); | |
| } | |
| /** | |
| * 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 | |
| * | |
| * @throws NullPointerException if <code>attributes</code> is | |
| * <code>null</code>. | |
| * @throws IllegalArgumentException if the subrange is not valid. | |
| */ | |
| public void addAttributes(Map attributes, int begin_index, int end_index) | |
| { | |
| if (attributes == null) | |
| throw new NullPointerException("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); | |
| } | |
| /** | |
| * 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(), | |
| null)); | |
| } | |
| /** | |
| * 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())); | |
| } | |
| /** | |
| * 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 |