Home » openjdk-7 » java » text » [javadoc | source]

    1   /* AttributedStringIterator.java -- Class to iterate over AttributedString
    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.HashMap;
   42   import java.util.HashSet;
   43   import java.util.Iterator;
   44   import java.util.Map;
   45   import java.util.Set;
   46   
   47   /**
   48     * This class implements the AttributedCharacterIterator interface.  It
   49     * is used by AttributedString.getIterator().
   50     *
   51     * @version 0.0
   52     *
   53     * @author Aaron M. Renn (arenn@urbanophile.com)
   54     */
   55   class AttributedStringIterator implements AttributedCharacterIterator
   56   {
   57   
   58     /*************************************************************************/
   59   
   60     /** The character iterator containing the text */
   61     private CharacterIterator ci;
   62   
   63     /** The list of attributes and ranges */
   64     private AttributedString.AttributeRange[] attribs;
   65   
   66     /**
   67      * The list of attributes that the user is interested in.  We may,
   68      * at our option, not return any other attributes.
   69      */
   70     private AttributedCharacterIterator.Attribute[] restricts;
   71   
   72     /*************************************************************************/
   73   
   74     AttributedStringIterator(StringCharacterIterator sci, 
   75                              AttributedString.AttributeRange[] attribs,
   76                              int begin_index, int end_index,
   77                              AttributedCharacterIterator.Attribute[] restricts)
   78     {
   79       this.ci = new StringCharacterIterator(sci, begin_index, end_index);
   80       this.attribs = attribs;
   81       this.restricts = restricts;
   82     }
   83   
   84     /*************************************************************************/
   85   
   86     // First we have a bunch of stupid redirects.  If StringCharacterIterator
   87     // weren't final, I just would have extended that for this class.  Alas, no.
   88   
   89     public Object clone()
   90     {
   91       return(ci.clone());
   92     }
   93   
   94     public char current()
   95     {
   96       return(ci.current());
   97     }
   98   
   99     public char next()
  100     {
  101       return(ci.next());
  102     }
  103   
  104     public char previous()
  105     {
  106       return(ci.previous());
  107     }
  108   
  109     public char first()
  110     {
  111       return(ci.first());
  112     }
  113   
  114     public char last()
  115     {
  116       return(ci.last());
  117     }
  118   
  119     public int getIndex()
  120     {
  121       return(ci.getIndex());
  122     }
  123   
  124     public char setIndex(int index)
  125     {
  126       return(ci.setIndex(index));  
  127     }
  128   
  129     public int getBeginIndex()
  130     {
  131       return(ci.getBeginIndex());
  132     }
  133   
  134     public int getEndIndex()
  135     {
  136       return(ci.getEndIndex());
  137     }
  138   
  139     /*
  140      * Here is where the AttributedCharacterIterator methods start.
  141      */ 
  142   
  143     /*************************************************************************/
  144   
  145     /**
  146      * Returns a list of all the attribute keys that are defined anywhere
  147      * on this string.
  148      */
  149     public Set getAllAttributeKeys()
  150     {
  151       HashSet s = new HashSet();
  152       if (attribs == null)
  153         return(s);
  154   
  155       for (int i = 0; i < attribs.length; i++)
  156       {
  157         if (attribs[i].begin_index > getEndIndex()
  158   	  || attribs[i].end_index <= getBeginIndex())
  159   	continue;
  160   
  161         Set key_set = attribs[i].attribs.keySet();
  162         Iterator iter = key_set.iterator();
  163         while (iter.hasNext())
  164           {
  165             s.add(iter.next());
  166           }
  167       }
  168   
  169       return(s);
  170     }
  171   
  172     /*************************************************************************/
  173   
  174     /**
  175      * Various methods that determine how far the run extends for various
  176      * attribute combinations.
  177      */
  178   
  179     public int getRunLimit()
  180     {
  181       return(getRunLimit(getAttributes().keySet()));
  182     }
  183   
  184     public int getRunLimit(AttributedCharacterIterator.Attribute attrib)
  185     {
  186       HashSet s = new HashSet();
  187       s.add(attrib);
  188       return(getRunLimit(s));
  189     }
  190   
  191     public synchronized int getRunLimit(Set attributeSet)
  192     {
  193       if (attributeSet == null)
  194         return ci.getEndIndex();
  195       
  196       int current = ci.getIndex();
  197       int end = ci.getEndIndex();
  198       int limit = current;
  199       if (current == end) 
  200         return end;
  201       Map runValues = getAttributes();
  202       while (limit < end) 
  203       {
  204         Iterator iterator = attributeSet.iterator();
  205         while (iterator.hasNext()) 
  206         {
  207   	// Qualified name is a workaround for a gcj 4.0 bug.
  208           AttributedCharacterIterator.Attribute attributeKey
  209   	  = (AttributedCharacterIterator.Attribute) iterator.next();
  210           Object v1 = runValues.get(attributeKey);
  211           Object v2 = getAttribute(attributeKey, limit + 1);
  212           boolean changed = false;
  213           // check for equal or both null, if NO return start
  214           if (v1 != null) 
  215             {
  216               changed = !v1.equals(v2);
  217             }
  218           else 
  219             {
  220               changed = (v2 != null);  
  221             }
  222           if (changed)
  223             return limit + 1;
  224         }
  225         // no differences, so increment limit and next and loop again
  226         limit++;
  227       }
  228       return end;
  229     }
  230   
  231     /*************************************************************************/
  232   
  233     /**
  234      * Various methods that determine where the run begins for various
  235      * attribute combinations.
  236      */
  237   
  238     /**
  239      * Returns the index of the first character in the run containing the current
  240      * character and defined by all the attributes defined for that character
  241      * position.
  242      * 
  243      * @return The run start index.
  244      */
  245     public int getRunStart()
  246     {
  247       return(getRunStart(getAttributes().keySet()));
  248     }
  249   
  250     /**
  251      * Returns the index of the first character in the run, defined by the 
  252      * specified attribute, that contains the current character.
  253      * 
  254      * @param attrib  the attribute (<code>null</code> permitted).
  255      * 
  256      * return The index of the first character in the run.
  257      */
  258     public int getRunStart(AttributedCharacterIterator.Attribute attrib)
  259     {
  260       if (attrib == null)
  261         return ci.getBeginIndex();
  262       HashSet s = new HashSet();
  263       s.add(attrib);
  264       return(getRunStart(s));
  265     }
  266   
  267     /**
  268      * Returns the index of the first character in the run, defined by the 
  269      * specified attribute set, that contains the current character.
  270      * 
  271      * @param attributeSet  the attribute set (<code>null</code> permitted).
  272      * 
  273      * return The index of the first character in the run.
  274      */
  275     public int getRunStart(Set attributeSet)
  276     {
  277       if (attributeSet == null)
  278         return ci.getBeginIndex();
  279       
  280       int current = ci.getIndex();
  281       int begin = ci.getBeginIndex();
  282       int start = current;
  283       if (start == begin) 
  284         return begin;
  285       Map runValues = getAttributes();
  286       int prev = start - 1;
  287       while (start > begin) 
  288       {
  289         Iterator iterator = attributeSet.iterator();
  290         while (iterator.hasNext()) 
  291         {
  292   	// Qualified name is a workaround for a gcj 4.0 bug.
  293           AttributedCharacterIterator.Attribute attributeKey
  294   	  = (AttributedCharacterIterator.Attribute) iterator.next();
  295           Object v1 = runValues.get(attributeKey);
  296           Object v2 = getAttribute(attributeKey, prev);
  297           boolean changed = false;
  298           // check for equal or both null, if NO return start
  299           if (v1 != null) 
  300             {
  301               changed = !v1.equals(v2);
  302             }
  303           else 
  304             {
  305               changed = (v2 != null);  
  306             }
  307           if (changed)
  308             return start;
  309         }
  310         // no differences, so decrement start and prev and loop again
  311         start--;
  312         prev--;
  313       }
  314       return start;
  315     }
  316   
  317     /*************************************************************************/
  318   
  319     /**
  320      * Returns the value for an attribute at the specified position.  If the
  321      * attribute key (<code>key</code>) is <code>null</code>, the method returns
  322      * <code>null</code>.
  323      * 
  324      * @param key  the key (<code>null</code> permitted).
  325      * @param pos  the character position.
  326      * 
  327      * @return The attribute value (possibly <code>null</code>).
  328      */
  329     private Object getAttribute(AttributedCharacterIterator.Attribute key, 
  330             int pos)
  331     {
  332       if (attribs == null)
  333         return null;
  334       for (int i = attribs.length - 1; i >= 0; i--)
  335         {
  336           if (pos >= attribs[i].begin_index && pos < attribs[i].end_index)
  337             {
  338               Set keys = attribs[i].attribs.keySet();
  339               if (keys.contains(key)) 
  340                 {
  341                   return attribs[i].attribs.get(key);
  342                 }
  343             }
  344         }
  345       return null;   
  346     }
  347     
  348     /**
  349      * Returns the value for an attribute at the current position.  If the
  350      * attribute key (<code>key</code>) is <code>null</code>, the method returns
  351      * <code>null</code>.
  352      * 
  353      * @param key  the key (<code>null</code> permitted).
  354      * 
  355      * @return The attribute value (possibly <code>null</code>).
  356      */
  357     public Object getAttribute(AttributedCharacterIterator.Attribute key)
  358     {
  359       return getAttribute(key, ci.getIndex());
  360     }
  361   
  362     /*************************************************************************/
  363   
  364     /**
  365      * Return a list of all the attributes and values defined for this
  366      * character
  367      */
  368     public Map getAttributes()
  369     {
  370       HashMap m = new HashMap();
  371       if (attribs == null)
  372         return(m);
  373     
  374       for (int i = 0; i < attribs.length; i++)
  375         {
  376            if ((ci.getIndex() >= attribs[i].begin_index) &&
  377                (ci.getIndex() < attribs[i].end_index))
  378              m.putAll(attribs[i].attribs);
  379         }
  380   
  381       return(m);
  382     }
  383   
  384   } // class AttributedStringIterator

Home » openjdk-7 » java » text » [javadoc | source]