1:
38: package ;
39:
40: import ;
41: import ;
42: import ;
43: import ;
44: import ;
45: import ;
46: import ;
47: import ;
48:
49: import java.text.AttributedCharacterIterator.Attribute;
50:
51:
62: public class FormatCharacterIterator implements AttributedCharacterIterator
63: {
64: private String formattedString;
65: private int charIndex;
66: private int attributeIndex;
67: private int[] ranges;
68: private List<Map<Attribute,Object>> attributes;
69: private static final boolean DEBUG = false;
70:
71:
76: public FormatCharacterIterator()
77: {
78: formattedString = "";
79: ranges = new int[0];
80: attributes = new ArrayList<Map<Attribute,Object>>(0);
81: }
82:
83:
98: public FormatCharacterIterator (String s, int[] ranges,
99: List<Map<Attribute,Object>> attributes)
100: {
101: formattedString = s;
102: this.ranges = ranges;
103: this.attributes = attributes;
104: }
105:
106:
110:
111: public Set<Attribute> getAllAttributeKeys()
112: {
113: if (attributes != null && attributes.get(attributeIndex) != null)
114: return attributes.get(attributeIndex).keySet();
115: else
116: return new HashSet<Attribute>();
117: }
118:
119: public Map<Attribute,Object> getAttributes()
120: {
121: if (attributes != null && attributes.get(attributeIndex) != null)
122: return attributes.get(attributeIndex);
123: else
124: return new HashMap<Attribute,Object>();
125: }
126:
127: public Object getAttribute (Attribute attrib)
128: {
129: if (attributes != null && attributes.get(attributeIndex) != null)
130: return attributes.get(attributeIndex).get (attrib);
131: else
132: return null;
133: }
134:
135: public int getRunLimit(Set<? extends Attribute> reqAttrs)
136: {
137: if (attributes == null)
138: return formattedString.length();
139:
140: int currentAttrIndex = attributeIndex;
141: Set<Attribute> newKeys;
142:
143: do
144: {
145: currentAttrIndex++;
146: if (currentAttrIndex == attributes.size())
147: return formattedString.length();
148: Map<Attribute,Object> currentAttr =
149: attributes.get(currentAttrIndex);
150: if (currentAttr == null)
151: break;
152: newKeys = currentAttr.keySet();
153: }
154: while (newKeys.containsAll (reqAttrs));
155:
156: return ranges[currentAttrIndex-1];
157: }
158:
159: public int getRunLimit (Attribute attribute)
160: {
161: Set<Attribute> s = new HashSet<Attribute>();
162:
163: s.add (attribute);
164: return getRunLimit (s);
165: }
166:
167: public int getRunLimit()
168: {
169: if (attributes == null)
170: return formattedString.length();
171: if (attributes.get(attributeIndex) == null)
172: {
173: for (int i=attributeIndex+1;i<attributes.size();i++)
174: if (attributes.get(i) != null)
175: return ranges[i-1];
176: return formattedString.length();
177: }
178:
179: return getRunLimit (attributes.get(attributeIndex).keySet());
180: }
181:
182: public int getRunStart (Set<? extends Attribute> reqAttrs)
183: {
184: if (attributes == null)
185: return formattedString.length();
186:
187: int currentAttrIndex = attributeIndex;
188: Set<Attribute> newKeys = null;
189:
190: do
191: {
192: if (currentAttrIndex == 0)
193: return 0;
194:
195: currentAttrIndex--;
196: Map<Attribute,Object> currentAttr =
197: attributes.get(currentAttrIndex);
198: if (currentAttr == null)
199: break;
200: newKeys = currentAttr.keySet();
201: }
202: while (newKeys.containsAll (reqAttrs));
203:
204: return (currentAttrIndex > 0) ? ranges[currentAttrIndex-1] : 0;
205: }
206:
207: public int getRunStart()
208: {
209: if (attributes == null)
210: return 0;
211:
212: Map<Attribute,Object> attrib = attributes.get(attributeIndex);
213: if (attrib == null)
214: {
215: for (int i=attributeIndex;i>0;i--)
216: if (attributes.get(i) != null)
217: return ranges[attributeIndex-1];
218: return 0;
219: }
220:
221: return getRunStart (attrib.keySet());
222: }
223:
224: public int getRunStart (Attribute attribute)
225: {
226: Set<Attribute> s = new HashSet<Attribute>();
227:
228: s.add (attribute);
229: return getRunStart (s);
230: }
231:
232: public Object clone()
233: {
234: return new FormatCharacterIterator (formattedString, ranges, attributes);
235: }
236:
237:
241:
242: public char current()
243: {
244: return formattedString.charAt (charIndex);
245: }
246:
247: public char first()
248: {
249: charIndex = 0;
250: attributeIndex = 0;
251: return formattedString.charAt (0);
252: }
253:
254: public int getBeginIndex()
255: {
256: return 0;
257: }
258:
259: public int getEndIndex()
260: {
261: return formattedString.length();
262: }
263:
264: public int getIndex()
265: {
266: return charIndex;
267: }
268:
269: public char last()
270: {
271: charIndex = formattedString.length()-1;
272: if (attributes != null)
273: attributeIndex = attributes.size()-1;
274: return formattedString.charAt (charIndex);
275: }
276:
277: public char next()
278: {
279: charIndex++;
280: if (charIndex >= formattedString.length())
281: {
282: charIndex = getEndIndex();
283: return DONE;
284: }
285: if (attributes != null)
286: {
287: if (charIndex >= ranges[attributeIndex])
288: attributeIndex++;
289: }
290: return formattedString.charAt (charIndex);
291: }
292:
293: public char previous()
294: {
295: charIndex--;
296: if (charIndex < 0)
297: {
298: charIndex = 0;
299: return DONE;
300: }
301:
302: if (attributes != null)
303: {
304: if (charIndex < ranges[attributeIndex])
305: attributeIndex--;
306: }
307: return formattedString.charAt (charIndex);
308: }
309:
310: public char setIndex (int position)
311: {
312: if (position < 0 || position > formattedString.length())
313: throw new IllegalArgumentException ("position is out of range");
314:
315: charIndex = position;
316: if (attributes != null)
317: {
318: for (attributeIndex=0;attributeIndex<attributes.size();
319: attributeIndex++)
320: if (ranges[attributeIndex] > charIndex)
321: break;
322: attributeIndex--;
323: }
324: if (charIndex == formattedString.length())
325: return DONE;
326: else
327: return formattedString.charAt (charIndex);
328: }
329:
330:
339: public void mergeAttributes (List<Map<Attribute,Object>> attributes,
340: int[] ranges)
341: {
342: List<Integer> newRanges = new ArrayList<Integer>();
343: List<Map<Attribute,Object>> newAttributes =
344: new ArrayList<Map<Attribute,Object>>();
345: int i = 0, j = 0;
346:
347: debug("merging " + attributes.size() + " attrs");
348:
349: while (i < this.ranges.length && j < ranges.length)
350: {
351: if (this.attributes.get(i) != null)
352: {
353: newAttributes.add (this.attributes.get(i));
354: if (attributes.get(j) != null)
355: this.attributes.get(i).putAll (attributes.get(j));
356: }
357: else
358: {
359: newAttributes.add (attributes.get(j));
360: }
361: if (this.ranges[i] == ranges[j])
362: {
363: newRanges.add (Integer.valueOf (ranges[j]));
364: i++;
365: j++;
366: }
367: else if (this.ranges[i] < ranges[j])
368: {
369: newRanges.add (Integer.valueOf (this.ranges[i]));
370: i++;
371: }
372: else
373: {
374: newRanges.add (Integer.valueOf (ranges[j]));
375: j++;
376: }
377: }
378:
379: if (i != this.ranges.length)
380: {
381: for (;i<this.ranges.length;i++)
382: {
383: newAttributes.add (this.attributes.get(i));
384: newRanges.add (Integer.valueOf (this.ranges[i]));
385: }
386: }
387: if (j != ranges.length)
388: {
389: for (;j<ranges.length;j++)
390: {
391: newAttributes.add (attributes.get(j));
392: newRanges.add (Integer.valueOf (ranges[j]));
393: }
394: }
395:
396: this.attributes = newAttributes;
397: this.ranges = new int[newRanges.size()];
398:
399: for (i=0;i<newRanges.size();i++)
400: {
401: this.ranges[i] = newRanges.get (i).intValue();
402: }
403:
404: dumpTable();
405: }
406:
407:
414: public void append (AttributedCharacterIterator iterator)
415: {
416: char c = iterator.first();
417: List<Integer> moreRanges = new ArrayList<Integer>();
418: List<Map<Attribute,Object>> moreAttributes =
419: new ArrayList<Map<Attribute,Object>>();
420:
421: do
422: {
423: formattedString = formattedString + String.valueOf (c);
424:
425: moreAttributes.add (iterator.getAttributes());
426: moreRanges.add (Integer.valueOf (formattedString.length()));
427:
428: c = iterator.next();
429: }
430: while (c != DONE);
431:
432: List<Map<Attribute,Object>> newAttributes =
433: new ArrayList<Map<Attribute,Object>>(attributes.size() + moreAttributes.size());
434: int[] newRanges = new int[ranges.length + moreRanges.size()];
435:
436: newAttributes.addAll(attributes);
437: newAttributes.addAll(moreAttributes);
438:
439: System.arraycopy (ranges, 0, newRanges, 0, ranges.length);
440: Integer[] newRangesArray = moreRanges.toArray(new Integer[moreRanges.size()]);
441: for (int i = 0; i < moreRanges.size();i++)
442: newRanges[i+ranges.length] = newRangesArray[i].intValue();
443:
444: attributes = newAttributes;
445: ranges = newRanges;
446: }
447:
448:
457: public void append (String text, HashMap<? extends Attribute,? extends Object> localAttributes)
458: {
459: int[] newRanges = new int[ranges.length+1];
460: List<Map<Attribute,Object>> newAttributes =
461: new ArrayList<Map<Attribute,Object>>(attributes.size()+1);
462:
463: formattedString += text;
464: newAttributes.addAll(attributes);
465: System.arraycopy (ranges, 0, newRanges, 0, ranges.length);
466: newRanges[ranges.length] = formattedString.length();
467: newAttributes.add(new HashMap<Attribute,Object>(localAttributes));
468:
469: ranges = newRanges;
470: attributes = newAttributes;
471: }
472:
473:
480: public void append (String text)
481: {
482: append (text, null);
483: }
484:
485:
498: public void addAttributes(Map<? extends Attribute,? extends Object> attributes,
499: int rangeStart, int rangeEnd)
500: {
501: List<Map<Attribute,Object>> mergeAttribs = new ArrayList<Map<Attribute,Object>>();
502: int[] mergeRanges;
503:
504: if (rangeStart == 0)
505: mergeRanges = new int[] { rangeEnd };
506: else
507: {
508: mergeRanges = new int[] { rangeStart, rangeEnd };
509: mergeAttribs.add(null);
510: }
511: mergeAttribs.add(new HashMap<Attribute,Object>(attributes));
512: mergeAttributes(mergeAttribs, mergeRanges);
513: }
514:
515: private void debug(String s)
516: {
517: if (DEBUG)
518: System.out.println(s);
519: }
520:
521: private void dumpTable()
522: {
523: int startRange = 0;
524:
525: if (!DEBUG)
526: return;
527:
528: System.out.println("Dumping internal table:");
529: for (int i = 0; i < ranges.length; i++)
530: {
531: System.out.print("\t" + startRange + " => " + ranges[i] + ":");
532: if (attributes.get(i) == null)
533: System.out.println("null");
534: else
535: {
536: Set<Attribute> keyset = attributes.get(i).keySet();
537: if (keyset != null)
538: {
539: Iterator<Attribute> keys = keyset.iterator();
540:
541: while (keys.hasNext())
542: System.out.print(" " + keys.next());
543: }
544: else
545: System.out.println("keySet null");
546: System.out.println();
547: }
548: }
549: System.out.println();
550: System.out.flush();
551: }
552: }