001 /* 002 * Copyright 2009 - 2009 JEuclid, http://jeuclid.sf.net 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017 /* $Id: MultiAttributedCharacterIterator.java,v 344ccd357471 2009/09/10 14:15:11 max $ */ 018 019 package net.sourceforge.jeuclid.elements.support.text; 020 021 import java.text.AttributedCharacterIterator; 022 import java.text.CharacterIterator; 023 import java.util.ArrayList; 024 import java.util.HashSet; 025 import java.util.List; 026 import java.util.Map; 027 import java.util.Set; 028 029 /** 030 * Joins multiple {@link AttributedCharacterIterator}s into one. 031 * 032 * @version $Revision: 344ccd357471 $ 033 */ 034 public class MultiAttributedCharacterIterator implements 035 AttributedCharacterIterator { 036 037 private final List<AttributedCharacterIterator> realIterators = new ArrayList<AttributedCharacterIterator>(); 038 039 private int currentList; 040 041 /** 042 * Default constructor. 043 */ 044 public MultiAttributedCharacterIterator() { 045 // nothing to do; 046 } 047 048 // CHECKSTYLE:OFF Clone is disabled. 049 @Override 050 public Object clone() { 051 throw new UnsupportedOperationException(); 052 } 053 054 // CHECKSTYLE: ON 055 056 /** 057 * Adds a new CharacterIterator 058 * 059 * @param aci 060 * the new CharacterIterator to add to the list. 061 */ 062 public void appendAttributedCharacterIterator( 063 final AttributedCharacterIterator aci) { 064 this.realIterators.add(aci); 065 this.first(); 066 } 067 068 private int sumUpToNotIncluding(final int limit) { 069 int offset = 0; 070 for (int i = 0; i < limit; i++) { 071 final AttributedCharacterIterator ci = this.realIterators.get(i); 072 offset += ci.getEndIndex() - ci.getBeginIndex(); 073 } 074 return offset; 075 } 076 077 private int currentOffset() { 078 int offset = this.sumUpToNotIncluding(this.currentList); 079 offset -= this.realIterators.get(this.currentList).getBeginIndex(); 080 return offset; 081 } 082 083 /** {@inheritDoc} */ 084 public Set<Attribute> getAllAttributeKeys() { 085 final Set<Attribute> retVal = new HashSet<Attribute>(); 086 for (final AttributedCharacterIterator ri : this.realIterators) { 087 retVal.addAll(ri.getAllAttributeKeys()); 088 } 089 return retVal; 090 } 091 092 /** {@inheritDoc} */ 093 public Object getAttribute(final Attribute attribute) { 094 return this.realIterators.get(this.currentList).getAttribute(attribute); 095 } 096 097 /** {@inheritDoc} */ 098 public Map<Attribute, Object> getAttributes() { 099 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 }