View Javadoc

1   /*
2    * Copyright 2009 - 2009 JEuclid, http://jeuclid.sf.net
3    * 
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  
17  /* $Id: MultiAttributedCharacterIterator.java,v 344ccd357471 2009/09/10 14:15:11 max $ */
18  
19  package net.sourceforge.jeuclid.elements.support.text;
20  
21  import java.text.AttributedCharacterIterator;
22  import java.text.CharacterIterator;
23  import java.util.ArrayList;
24  import java.util.HashSet;
25  import java.util.List;
26  import java.util.Map;
27  import java.util.Set;
28  
29  /**
30   * Joins multiple {@link AttributedCharacterIterator}s into one.
31   * 
32   * @version $Revision: 344ccd357471 $
33   */
34  public class MultiAttributedCharacterIterator implements
35          AttributedCharacterIterator {
36  
37      private final List<AttributedCharacterIterator> realIterators = new ArrayList<AttributedCharacterIterator>();
38  
39      private int currentList;
40  
41      /**
42       * Default constructor.
43       */
44      public MultiAttributedCharacterIterator() {
45          // nothing to do;
46      }
47  
48      // CHECKSTYLE:OFF Clone is disabled.
49      @Override
50      public Object clone() {
51          throw new UnsupportedOperationException();
52      }
53  
54      // CHECKSTYLE: ON
55  
56      /**
57       * Adds a new CharacterIterator
58       * 
59       * @param aci
60       *            the new CharacterIterator to add to the list.
61       */
62      public void appendAttributedCharacterIterator(
63              final AttributedCharacterIterator aci) {
64          this.realIterators.add(aci);
65          this.first();
66      }
67  
68      private int sumUpToNotIncluding(final int limit) {
69          int offset = 0;
70          for (int i = 0; i < limit; i++) {
71              final AttributedCharacterIterator ci = this.realIterators.get(i);
72              offset += ci.getEndIndex() - ci.getBeginIndex();
73          }
74          return offset;
75      }
76  
77      private int currentOffset() {
78          int offset = this.sumUpToNotIncluding(this.currentList);
79          offset -= this.realIterators.get(this.currentList).getBeginIndex();
80          return offset;
81      }
82  
83      /** {@inheritDoc} */
84      public Set<Attribute> getAllAttributeKeys() {
85          final Set<Attribute> retVal = new HashSet<Attribute>();
86          for (final AttributedCharacterIterator ri : this.realIterators) {
87              retVal.addAll(ri.getAllAttributeKeys());
88          }
89          return retVal;
90      }
91  
92      /** {@inheritDoc} */
93      public Object getAttribute(final Attribute attribute) {
94          return this.realIterators.get(this.currentList).getAttribute(attribute);
95      }
96  
97      /** {@inheritDoc} */
98      public Map<Attribute, Object> getAttributes() {
99          return this.realIterators.get(this.currentList).getAttributes();
100     }
101 
102     /** {@inheritDoc} */
103     public int getRunLimit() {
104         return this.realIterators.get(this.currentList).getRunLimit()
105                 + this.currentOffset();
106     }
107 
108     /** {@inheritDoc} */
109     public int getRunLimit(final Attribute attribute) {
110         return this.realIterators.get(this.currentList).getRunLimit(attribute)
111                 + this.currentOffset();
112     }
113 
114     /** {@inheritDoc} */
115     public int getRunLimit(final Set<? extends Attribute> attributes) {
116         return this.realIterators.get(this.currentList).getRunLimit(attributes)
117                 + this.currentOffset();
118     }
119 
120     /** {@inheritDoc} */
121     public int getRunStart() {
122         return this.realIterators.get(this.currentList).getRunStart()
123                 + this.currentOffset();
124     }
125 
126     /** {@inheritDoc} */
127     public int getRunStart(final Attribute attribute) {
128         return this.realIterators.get(this.currentList).getRunStart(attribute)
129                 + this.currentOffset();
130     }
131 
132     /** {@inheritDoc} */
133     public int getRunStart(final Set<? extends Attribute> attributes) {
134         return this.realIterators.get(this.currentList).getRunStart(attributes)
135                 + this.currentOffset();
136     }
137 
138     /** {@inheritDoc} */
139     public char current() {
140         return this.realIterators.get(this.currentList).current();
141     }
142 
143     /** {@inheritDoc} */
144     public char first() {
145         this.currentList = 0;
146         return this.realIterators.get(this.currentList).first();
147     }
148 
149     /** {@inheritDoc} */
150     public int getBeginIndex() {
151         return 0;
152     }
153 
154     /** {@inheritDoc} */
155     public int getEndIndex() {
156         return this.sumUpToNotIncluding(this.realIterators.size());
157     }
158 
159     /** {@inheritDoc} */
160     public int getIndex() {
161         return this.currentOffset()
162                 + this.realIterators.get(this.currentList).getIndex();
163     }
164 
165     /** {@inheritDoc} */
166     public char last() {
167         this.currentList = this.realIterators.size() - 1;
168         return this.realIterators.get(this.currentList).last();
169     }
170 
171     /** {@inheritDoc} */
172     public char next() {
173         char c = this.realIterators.get(this.currentList).next();
174         while ((c == CharacterIterator.DONE)
175                 && (this.currentList < this.realIterators.size() - 1)) {
176             this.currentList++;
177             c = this.realIterators.get(this.currentList).first();
178         }
179         return c;
180     }
181 
182     /** {@inheritDoc} */
183     public char previous() {
184         char c = this.realIterators.get(this.currentList).previous();
185         while ((c == CharacterIterator.DONE) && (this.currentList > 0)) {
186             this.currentList--;
187             c = this.realIterators.get(this.currentList).previous();
188         }
189         return c;
190     }
191 
192     /** {@inheritDoc} */
193     public char setIndex(final int position) {
194         int prev = 0;
195         int offset = 0;
196         for (int i = 0; i < this.realIterators.size(); i++) {
197             final AttributedCharacterIterator ci = this.realIterators.get(i);
198             prev = offset;
199             final int beginIndex = ci.getBeginIndex();
200             offset += ci.getEndIndex() - beginIndex;
201             if (((prev <= position) && (offset > position))
202                     || ((offset == position) && (i == this.realIterators.size() - 1))) {
203                 this.currentList = i;
204                 return ci.setIndex(beginIndex + position - prev);
205             }
206         }
207         throw new IllegalArgumentException();
208     }
209 }