1 /*
   2  * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 package java.text;
  26 
  27 import java.util.ArrayList;
  28 
  29 /**
  30  * CharacterIteratorFieldDelegate combines the notifications from a Format
  31  * into a resulting <code>AttributedCharacterIterator</code>. The resulting
  32  * <code>AttributedCharacterIterator</code> can be retrieved by way of
  33  * the <code>getIterator</code> method.
  34  *
  35  */
  36 class CharacterIteratorFieldDelegate implements Format.FieldDelegate {
  37     /**
  38      * Array of AttributeStrings. Whenever <code>formatted</code> is invoked
  39      * for a region > size, a new instance of AttributedString is added to
  40      * attributedStrings. Subsequent invocations of <code>formatted</code>
  41      * for existing regions result in invoking addAttribute on the existing
  42      * AttributedStrings.
  43      */
  44     private ArrayList<AttributedString> attributedStrings;
  45     /**
  46      * Running count of the number of characters that have
  47      * been encountered.
  48      */
  49     private int size;
  50 
  51 
  52     CharacterIteratorFieldDelegate() {
  53         attributedStrings = new ArrayList<>();
  54     }
  55 
  56     public void formatted(Format.Field attr, Object value, int start, int end,
  57                           StringBuffer buffer) {
  58         if (start != end) {
  59             if (start < size) {
  60                 // Adjust attributes of existing runs
  61                 int index = size;
  62                 int asIndex = attributedStrings.size() - 1;
  63 
  64                 while (start < index) {
  65                     AttributedString as = attributedStrings.
  66                                            get(asIndex--);
  67                     int newIndex = index - as.length();
  68                     int aStart = Math.max(0, start - newIndex);
  69 
  70                     as.addAttribute(attr, value, aStart, Math.min(
  71                                     end - start, as.length() - aStart) +
  72                                     aStart);
  73                     index = newIndex;
  74                 }
  75             }
  76             if (size < start) {
  77                 // Pad attributes
  78                 attributedStrings.add(new AttributedString(
  79                                           buffer.substring(size, start)));
  80                 size = start;
  81             }
  82             if (size < end) {
  83                 // Add new string
  84                 int aStart = Math.max(start, size);
  85                 AttributedString string = new AttributedString(
  86                                    buffer.substring(aStart, end));
  87 
  88                 string.addAttribute(attr, value);
  89                 attributedStrings.add(string);
  90                 size = end;
  91             }
  92         }
  93     }
  94 
  95     public void formatted(int fieldID, Format.Field attr, Object value,
  96                           int start, int end, StringBuffer buffer) {
  97         formatted(attr, value, start, end, buffer);
  98     }
  99 
 100     /**
 101      * Returns an <code>AttributedCharacterIterator</code> that can be used
 102      * to iterate over the resulting formatted String.
 103      *
 104      * @pararm string Result of formatting.
 105      */
 106     public AttributedCharacterIterator getIterator(String string) {
 107         // Add the last AttributedCharacterIterator if necessary
 108         // assert(size <= string.length());
 109         if (string.length() > size) {
 110             attributedStrings.add(new AttributedString(
 111                                   string.substring(size)));
 112             size = string.length();
 113         }
 114         int iCount = attributedStrings.size();
 115         AttributedCharacterIterator[] iterators = new
 116                                     AttributedCharacterIterator[iCount];
 117 
 118         for (int counter = 0; counter < iCount; counter++) {
 119             iterators[counter] = attributedStrings.
 120                                   get(counter).getIterator();
 121         }
 122         return new AttributedString(iterators).getIterator();
 123     }
 124 }