Source Code Cross Referenced for UnicodeMap.java in  » Internationalization-Localization » icu4j » com » ibm » icu » dev » test » util » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Internationalization Localization » icu4j » com.ibm.icu.dev.test.util 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        //##header
002:        /*
003:         *******************************************************************************
004:         * Copyright (C) 1996-2006, International Business Machines Corporation and    *
005:         * others. All Rights Reserved.                                                *
006:         *******************************************************************************
007:         */
008:        //#ifndef FOUNDATION
009:        package com.ibm.icu.dev.test.util;
010:
011:        import java.io.ByteArrayOutputStream;
012:        import java.io.DataInput;
013:        import java.io.DataOutput;
014:        import java.io.Externalizable;
015:        import java.io.IOException;
016:        import java.io.InputStream;
017:        import java.io.ObjectInput;
018:        import java.io.ObjectInputStream;
019:        import java.io.ObjectOutput;
020:        import java.io.ObjectOutputStream;
021:        import java.io.OutputStream;
022:        import java.io.Serializable;
023:        import java.util.ArrayList;
024:        import java.util.Collection;
025:        import java.util.Comparator;
026:        import java.util.HashMap;
027:        import java.util.HashSet;
028:        import java.util.Iterator;
029:        import java.util.LinkedHashMap;
030:        import java.util.LinkedHashSet;
031:        import java.util.List;
032:        import java.util.Map;
033:        import java.util.Set;
034:        import java.util.TreeSet;
035:
036:        import com.ibm.icu.impl.Utility;
037:        import com.ibm.icu.text.UTF16;
038:        import com.ibm.icu.text.UnicodeSet;
039:        import com.ibm.icu.text.UnicodeSetIterator;
040:        import com.ibm.icu.util.Freezable;
041:
042:        /**
043:         * Class for mapping Unicode characters to values
044:         * Much smaller storage than using HashMap, and much faster and more compact than
045:         * a list of UnicodeSets.
046:         * @author Davis
047:         */
048:
049:        public final class UnicodeMap implements  Cloneable, Freezable,
050:                Externalizable {
051:            static final boolean ASSERTIONS = false;
052:            static final long GROWTH_PERCENT = 200; // 100 is no growth!
053:            static final long GROWTH_GAP = 10; // extra bump!
054:
055:            private int length;
056:            // two parallel arrays to save memory. Wish Java had structs.
057:            private int[] transitions;
058:            private Object[] values;
059:
060:            private LinkedHashSet availableValues = new LinkedHashSet();
061:            private transient boolean staleAvailableValues;
062:
063:            private transient boolean errorOnReset;
064:            private transient boolean locked;
065:            private int lastIndex;
066:
067:            {
068:                clear();
069:            }
070:
071:            public UnicodeMap clear() {
072:                if (locked)
073:                    throw new UnsupportedOperationException(
074:                            "Attempt to modify locked object");
075:                length = 2;
076:                transitions = new int[] { 0, 0x110000, 0, 0, 0, 0, 0, 0, 0, 0 };
077:                values = new Object[10];
078:
079:                availableValues.clear();
080:                staleAvailableValues = false;
081:
082:                errorOnReset = false;
083:                lastIndex = 0;
084:                return this ;
085:            }
086:
087:            /* Boilerplate */
088:            public boolean equals(Object other) {
089:                if (other == null)
090:                    return false;
091:                try {
092:                    UnicodeMap that = (UnicodeMap) other;
093:                    if (length != that.length)
094:                        return false;
095:                    for (int i = 0; i < length - 1; ++i) {
096:                        if (transitions[i] != that.transitions[i])
097:                            return false;
098:                        if (!areEqual(values[i], that.values[i]))
099:                            return false;
100:                    }
101:                    return true;
102:                } catch (ClassCastException e) {
103:                    return false;
104:                }
105:            }
106:
107:            public int getHashCode(Object o) {
108:                return o.hashCode();
109:                //equator.getHashCode
110:            }
111:
112:            public static boolean areEqual(Object a, Object b) {
113:                if (a == b)
114:                    return true;
115:                if (a == null || b == null)
116:                    return false;
117:                return a.equals(b);
118:            }
119:
120:            public int hashCode() {
121:                int result = length;
122:                // TODO might want to abbreviate this for speed.
123:                for (int i = 0; i < length - 1; ++i) {
124:                    result = 37 * result + transitions[i];
125:                    result = 37 * result + getHashCode(values[i]);
126:                }
127:                return result;
128:            }
129:
130:            /**
131:             * Standard clone. Warning, as with Collections, does not do deep clone.
132:             */
133:            public Object cloneAsThawed() {
134:                UnicodeMap that = new UnicodeMap();
135:                that.length = length;
136:                that.transitions = (int[]) transitions.clone();
137:                that.values = (Object[]) values.clone();
138:                that.availableValues = new LinkedHashSet(availableValues);
139:                that.locked = false;
140:                return that;
141:            }
142:
143:            /* for internal consistency checking */
144:
145:            void _checkInvariants() {
146:                if (length < 2 || length > transitions.length
147:                        || transitions.length != values.length) {
148:                    throw new IllegalArgumentException(
149:                            "Invariant failed: Lengths bad");
150:                }
151:                for (int i = 1; i < length - 1; ++i) {
152:                    if (areEqual(values[i - 1], values[i])) {
153:                        throw new IllegalArgumentException(
154:                                "Invariant failed: values shared at " + "\t"
155:                                        + Utility.hex(i - 1) + ": <"
156:                                        + values[i - 1] + ">" + "\t"
157:                                        + Utility.hex(i) + ": <" + values[i]
158:                                        + ">");
159:                    }
160:                }
161:                if (transitions[0] != 0 || transitions[length - 1] != 0x110000) {
162:                    throw new IllegalArgumentException(
163:                            "Invariant failed: bounds set wrong");
164:                }
165:                for (int i = 1; i < length - 1; ++i) {
166:                    if (transitions[i - 1] >= transitions[i]) {
167:                        throw new IllegalArgumentException(
168:                                "Invariant failed: not monotonic" + "\t"
169:                                        + Utility.hex(i - 1) + ": "
170:                                        + transitions[i - 1] + "\t"
171:                                        + Utility.hex(i) + ": "
172:                                        + transitions[i]);
173:                    }
174:                }
175:            }
176:
177:            /**
178:             * Finds an index such that inversionList[i] <= codepoint < inversionList[i+1]
179:             * Assumes that 0 <= codepoint <= 0x10FFFF
180:             * @param codepoint
181:             * @return the index
182:             */
183:            private int _findIndex(int c) {
184:                int lo = 0;
185:                int hi = length - 1;
186:                int i = (lo + hi) >>> 1;
187:                // invariant: c >= list[lo]
188:                // invariant: c < list[hi]
189:                while (i != lo) {
190:                    if (c < transitions[i]) {
191:                        hi = i;
192:                    } else {
193:                        lo = i;
194:                    }
195:                    i = (lo + hi) >>> 1;
196:                }
197:                if (ASSERTIONS)
198:                    _checkFind(c, lo);
199:                return lo;
200:            }
201:
202:            private void _checkFind(int codepoint, int value) {
203:                int other = __findIndex(codepoint);
204:                if (other != value) {
205:                    throw new IllegalArgumentException(
206:                            "Invariant failed: binary search" + "\t"
207:                                    + Utility.hex(codepoint) + ": " + value
208:                                    + "\tshould be: " + other);
209:                }
210:            }
211:
212:            private int __findIndex(int codepoint) {
213:                // TODO use binary search
214:                for (int i = length - 1; i > 0; --i) {
215:                    if (transitions[i] <= codepoint)
216:                        return i;
217:                }
218:                return 0;
219:            }
220:
221:            /*
222:             * Try indexed lookup
223:             
224:            static final int SHIFT = 8;
225:            int[] starts = new int[0x10FFFF>>SHIFT]; // lowest transition index where codepoint>>x can be found
226:            boolean startsValid = false;
227:            private int findIndex(int codepoint) {
228:                if (!startsValid) {
229:                    int start = 0;
230:                    for (int i = 1; i < length; ++i) {
231:                        
232:                    }
233:                }
234:                for (int i = length-1; i > 0; --i) {
235:                   if (transitions[i] <= codepoint) return i;
236:               }
237:               return 0;
238:            }
239:             */
240:
241:            /**
242:             * Remove the items from index through index+count-1.
243:             * Logically reduces the size of the internal arrays.
244:             * @param index
245:             * @param count
246:             */
247:            private void _removeAt(int index, int count) {
248:                for (int i = index + count; i < length; ++i) {
249:                    transitions[i - count] = transitions[i];
250:                    values[i - count] = values[i];
251:                }
252:                length -= count;
253:            }
254:
255:            /**
256:             * Add a gap from index to index+count-1.
257:             * The values there are undefined, and must be set.
258:             * Logically grows arrays to accomodate. Actual growth is limited
259:             * @param index
260:             * @param count
261:             */
262:            private void _insertGapAt(int index, int count) {
263:                int newLength = length + count;
264:                int[] oldtransitions = transitions;
265:                Object[] oldvalues = values;
266:                if (newLength > transitions.length) {
267:                    int allocation = (int) (GROWTH_GAP + (newLength * GROWTH_PERCENT) / 100);
268:                    transitions = new int[allocation];
269:                    values = new Object[allocation];
270:                    for (int i = 0; i < index; ++i) {
271:                        transitions[i] = oldtransitions[i];
272:                        values[i] = oldvalues[i];
273:                    }
274:                }
275:                for (int i = length - 1; i >= index; --i) {
276:                    transitions[i + count] = oldtransitions[i];
277:                    values[i + count] = oldvalues[i];
278:                }
279:                length = newLength;
280:            }
281:
282:            /**
283:             * Associates code point with value. Removes any previous association.
284:             * @param codepoint
285:             * @param value
286:             * @return this, for chaining
287:             */
288:            private UnicodeMap _put(int codepoint, Object value) {
289:                // Warning: baseIndex is an invariant; must
290:                // be defined such that transitions[baseIndex] < codepoint
291:                // at end of this routine.
292:                int baseIndex;
293:                if (transitions[lastIndex] <= codepoint
294:                        && codepoint < transitions[lastIndex + 1]) {
295:                    baseIndex = lastIndex;
296:                } else {
297:                    baseIndex = _findIndex(codepoint);
298:                }
299:                int limitIndex = baseIndex + 1;
300:                // cases are (a) value is already set
301:                if (areEqual(values[baseIndex], value))
302:                    return this ;
303:                if (locked)
304:                    throw new UnsupportedOperationException(
305:                            "Attempt to modify locked object");
306:                if (errorOnReset && values[baseIndex] != null) {
307:                    throw new IllegalArgumentException(
308:                            "Attempt to reset value for "
309:                                    + Utility.hex(codepoint)
310:                                    + " when that is disallowed. Old: "
311:                                    + values[baseIndex] + "; New: " + value);
312:                }
313:
314:                // adjust the available values
315:                staleAvailableValues = true;
316:                availableValues.add(value); // add if not there already      
317:
318:                int baseCP = transitions[baseIndex];
319:                int limitCP = transitions[limitIndex];
320:                // we now start walking through the difference case,
321:                // based on whether we are at the start or end of range
322:                // and whether the range is a single character or multiple
323:
324:                if (baseCP == codepoint) {
325:                    // CASE: At very start of range
326:                    boolean connectsWithPrevious = baseIndex != 0
327:                            && areEqual(value, values[baseIndex - 1]);
328:
329:                    if (limitCP == codepoint + 1) {
330:                        // CASE: Single codepoint range
331:                        boolean connectsWithFollowing = baseIndex < length - 1
332:                                && areEqual(value, values[limitIndex]);
333:
334:                        if (connectsWithPrevious) {
335:                            // A1a connects with previous & following, so remove index
336:                            if (connectsWithFollowing) {
337:                                _removeAt(baseIndex, 2);
338:                            } else {
339:                                _removeAt(baseIndex, 1); // extend previous
340:                            }
341:                            --baseIndex; // fix up
342:                        } else if (connectsWithFollowing) {
343:                            _removeAt(baseIndex, 1); // extend following backwards
344:                            transitions[baseIndex] = codepoint;
345:                        } else {
346:                            // doesn't connect on either side, just reset
347:                            values[baseIndex] = value;
348:                        }
349:                    } else if (connectsWithPrevious) {
350:                        // A.1: start of multi codepoint range
351:                        // if connects
352:                        ++transitions[baseIndex]; // extend previous
353:                    } else {
354:                        // otherwise insert new transition
355:                        transitions[baseIndex] = codepoint + 1; // fix following range
356:                        _insertGapAt(baseIndex, 1);
357:                        values[baseIndex] = value;
358:                        transitions[baseIndex] = codepoint;
359:                    }
360:                } else if (limitCP == codepoint + 1) {
361:                    // CASE: at end of range        
362:                    // if connects, just back up range
363:                    boolean connectsWithFollowing = baseIndex < length - 1
364:                            && areEqual(value, values[limitIndex]);
365:
366:                    if (connectsWithFollowing) {
367:                        --transitions[limitIndex];
368:                        return this ;
369:                    } else {
370:                        _insertGapAt(limitIndex, 1);
371:                        transitions[limitIndex] = codepoint;
372:                        values[limitIndex] = value;
373:                    }
374:                } else {
375:                    // CASE: in middle of range
376:                    // insert gap, then set the new range
377:                    _insertGapAt(++baseIndex, 2);
378:                    transitions[baseIndex] = codepoint;
379:                    values[baseIndex] = value;
380:                    transitions[baseIndex + 1] = codepoint + 1;
381:                    values[baseIndex + 1] = values[baseIndex - 1]; // copy lower range values
382:                }
383:                lastIndex = baseIndex; // store for next time
384:                return this ;
385:            }
386:
387:            private UnicodeMap _putAll(int startCodePoint, int endCodePoint,
388:                    Object value) {
389:                for (int i = startCodePoint; i <= endCodePoint; ++i) {
390:                    _put(i, value);
391:                }
392:                return this ;
393:            }
394:
395:            /**
396:             * Sets the codepoint value.
397:             * @param codepoint
398:             * @param value
399:             * @return this (for chaining)
400:             */
401:            public UnicodeMap put(int codepoint, Object value) {
402:                if (codepoint < 0 || codepoint > 0x10FFFF) {
403:                    throw new IllegalArgumentException(
404:                            "Codepoint out of range: " + codepoint);
405:                }
406:                _put(codepoint, value);
407:                if (ASSERTIONS)
408:                    _checkInvariants();
409:                return this ;
410:            }
411:
412:            /**
413:             * Adds bunch o' codepoints; otherwise like put.
414:             * @param codepoints
415:             * @param value
416:             * @return this (for chaining)
417:             */
418:            public UnicodeMap putAll(UnicodeSet codepoints, Object value) {
419:                // TODO optimize
420:                UnicodeSetIterator it = new UnicodeSetIterator(codepoints);
421:                while (it.nextRange()) {
422:                    _putAll(it.codepoint, it.codepointEnd, value);
423:                }
424:                return this ;
425:            }
426:
427:            /**
428:             * Adds bunch o' codepoints; otherwise like add.
429:             * @param startCodePoint
430:             * @param endCodePoint
431:             * @param value
432:             * @return this (for chaining)
433:             */
434:            public UnicodeMap putAll(int startCodePoint, int endCodePoint,
435:                    Object value) {
436:                if (startCodePoint < 0 || endCodePoint > 0x10FFFF) {
437:                    throw new IllegalArgumentException(
438:                            "Codepoint out of range: "
439:                                    + Utility.hex(startCodePoint) + ".."
440:                                    + Utility.hex(endCodePoint));
441:                }
442:                // TODO optimize
443:                for (int i = startCodePoint; i <= endCodePoint; ++i) {
444:                    _put(i, value);
445:                }
446:                return this ;
447:            }
448:
449:            /**
450:             * Add all the (main) values from a Unicode property
451:             * @param prop the property to add to the map
452:             * @return this (for chaining)
453:             */
454:            public UnicodeMap putAll(UnicodeProperty prop) {
455:                // TODO optimize
456:                for (int i = 0; i <= 0x10FFFF; ++i) {
457:                    _put(i, prop.getValue(i));
458:                }
459:                return this ;
460:            }
461:
462:            /**
463:             * Add all the (main) values from a Unicode property
464:             * @param prop the property to add to the map
465:             * @return this (for chaining)
466:             */
467:            public UnicodeMap putAll(UnicodeMap prop) {
468:                // TODO optimize
469:                for (int i = 0; i <= 0x10FFFF; ++i) {
470:                    _put(i, prop.getValue(i));
471:                }
472:                return this ;
473:            }
474:
475:            /**
476:             * Set the currently unmapped Unicode code points to the given value.
477:             * @param value the value to set
478:             * @return this (for chaining)
479:             */
480:            public UnicodeMap setMissing(Object value) {
481:                // fast path, if value not yet present
482:                if (!getAvailableValues().contains(value)) {
483:                    staleAvailableValues = true;
484:                    availableValues.add(value);
485:                    for (int i = 0; i < length; ++i) {
486:                        if (values[i] == null)
487:                            values[i] = value;
488:                    }
489:                    return this ;
490:                } else {
491:                    return putAll(getSet(null), value);
492:                }
493:            }
494:
495:            /**
496:             * Returns the set associated with a given value. Deposits into
497:             * result if it is not null. Remember to clear if you just want
498:             * the new values.
499:             * @param value
500:             * @param result
501:             * @return result
502:             */
503:            public UnicodeSet getSet(Object value, UnicodeSet result) {
504:                if (result == null)
505:                    result = new UnicodeSet();
506:                for (int i = 0; i < length - 1; ++i) {
507:                    if (areEqual(value, values[i])) {
508:                        result.add(transitions[i], transitions[i + 1] - 1);
509:                    }
510:                }
511:                return result;
512:            }
513:
514:            public UnicodeSet getSet(Object value) {
515:                return getSet(value, null);
516:            }
517:
518:            public UnicodeSet keySet() {
519:                return getSet(null, null).complement();
520:            }
521:
522:            /**
523:             * Returns the list of possible values. Deposits each non-null value into
524:             * result. Creates result if it is null. Remember to clear result if
525:             * you are not appending to existing collection.
526:             * @param result
527:             * @return result
528:             */
529:            public Collection getAvailableValues(Collection result) {
530:                if (staleAvailableValues) {
531:                    // collect all the current values
532:                    // retain them in the availableValues
533:                    Set temp = new HashSet();
534:                    for (int i = 0; i < length - 1; ++i) {
535:                        if (values[i] != null)
536:                            temp.add(values[i]);
537:                    }
538:                    availableValues.retainAll(temp);
539:                    staleAvailableValues = false;
540:                }
541:                if (result == null)
542:                    result = new ArrayList(availableValues.size());
543:                result.addAll(availableValues);
544:                return result;
545:            }
546:
547:            /**
548:             * Convenience method
549:             */
550:            public Collection getAvailableValues() {
551:                return getAvailableValues(null);
552:            }
553:
554:            /**
555:             * Gets the value associated with a given code point.
556:             * Returns null, if there is no such value.
557:             * @param codepoint
558:             * @return the value
559:             */
560:            public Object getValue(int codepoint) {
561:                if (codepoint < 0 || codepoint > 0x10FFFF) {
562:                    throw new IllegalArgumentException(
563:                            "Codepoint out of range: " + codepoint);
564:                }
565:                return values[_findIndex(codepoint)];
566:            }
567:
568:            /**
569:             * Change a new string from the source string according to the mappings. For each code point cp, if getValue(cp) is null, append the character, otherwise append getValue(cp).toString()
570:             * @param source
571:             * @return
572:             */
573:            public String fold(String source) {
574:                StringBuffer result = new StringBuffer();
575:                int cp;
576:                for (int i = 0; i < source.length(); i += UTF16
577:                        .getCharCount(cp)) {
578:                    cp = UTF16.charAt(source, i);
579:                    Object mResult = getValue(cp);
580:                    if (mResult != null) {
581:                        result.append(mResult);
582:                    } else {
583:                        UTF16.append(result, cp);
584:                    }
585:                }
586:                return result.toString();
587:            }
588:
589:            public interface Composer {
590:                Object compose(int codePoint, Object a, Object b);
591:            }
592:
593:            public UnicodeMap composeWith(UnicodeMap other, Composer composer) {
594:                for (int i = 0; i <= 0x10FFFF; ++i) {
595:                    Object v1 = getValue(i);
596:                    Object v2 = other.getValue(i);
597:                    Object v3 = composer.compose(i, v1, v2);
598:                    if (v1 != v3 && (v1 == null || !v1.equals(v3)))
599:                        put(i, v3);
600:                }
601:                return this ;
602:            }
603:
604:            public UnicodeMap composeWith(UnicodeSet set, Object value,
605:                    Composer composer) {
606:                for (UnicodeSetIterator it = new UnicodeSetIterator(set); it
607:                        .next();) {
608:                    int i = it.codepoint;
609:                    Object v1 = getValue(i);
610:                    Object v3 = composer.compose(i, v1, value);
611:                    if (v1 != v3 && (v1 == null || !v1.equals(v3)))
612:                        put(i, v3);
613:                }
614:                return this ;
615:            }
616:
617:            /**
618:             * Follow the style used by UnicodeSetIterator
619:             */
620:            public static class MapIterator {
621:                public int codepoint;
622:                public int codepointEnd;
623:                public Object value;
624:
625:                private UnicodeMap map;
626:                private int index;
627:                private int startRange;
628:                private int endRange;
629:                private Object lastValue;
630:
631:                public MapIterator(UnicodeMap map) {
632:                    reset(map);
633:                }
634:
635:                // note: length of 2 means {0, 110000}. Only want to index up to 0!
636:                public boolean nextRange() {
637:                    if (index < 0 || index >= map.length - 1)
638:                        return false;
639:                    value = map.values[index];
640:                    codepoint = startRange = map.transitions[index++];
641:                    codepointEnd = endRange = map.transitions[index] - 1; // -1 to make limit into end
642:                    return true;
643:                }
644:
645:                public boolean next() {
646:                    if (startRange > endRange) {
647:                        //System.out.println("***" + Utility.hex(startRange) + ".." + Utility.hex(endRange));
648:                        if (!nextRange())
649:                            return false;
650:                        // index now points AFTER the start of the range
651:                        lastValue = map.values[index - 1];
652:                        //System.out.println("***" + Utility.hex(codepoint) + ".." + Utility.hex(codepointEnd) + " => " + lastValue);
653:                    }
654:                    value = lastValue;
655:                    codepoint = codepointEnd = startRange++; // set to first, and iterate
656:                    return true;
657:                }
658:
659:                public MapIterator reset() {
660:                    index = 0;
661:                    startRange = 0;
662:                    endRange = -1;
663:                    return this ;
664:                }
665:
666:                public MapIterator reset(UnicodeMap map) {
667:                    this .map = map;
668:                    return reset();
669:                }
670:            }
671:
672:            public String toString() {
673:                return toString(null);
674:            }
675:
676:            public String toString(Comparator collected) {
677:                StringBuffer result = new StringBuffer();
678:                if (collected == null) {
679:                    for (int i = 0; i < length - 1; ++i) {
680:                        Object value = values[i];
681:                        if (value == null)
682:                            continue;
683:                        int start = transitions[i];
684:                        int end = transitions[i + 1] - 1;
685:                        result.append(Utility.hex(start));
686:                        if (start != end)
687:                            result.append("..").append(Utility.hex(end));
688:                        result.append("\t=> ").append(
689:                                values[i] == null ? "null" : values[i]
690:                                        .toString()).append("\r\n");
691:                    }
692:                } else {
693:                    Set set = (Set) getAvailableValues(new TreeSet(collected));
694:                    for (Iterator it = set.iterator(); it.hasNext();) {
695:                        Object value = it.next();
696:                        UnicodeSet s = getSet(value);
697:                        result.append(value).append("\t=> ").append(
698:                                s.toPattern(true)).append("\r\n");
699:                    }
700:                }
701:                return result.toString();
702:            }
703:
704:            /**
705:             * @return Returns the errorOnReset.
706:             */
707:            public boolean getErrorOnReset() {
708:                return errorOnReset;
709:            }
710:
711:            /**
712:             * @param errorOnReset The errorOnReset to set.
713:             */
714:            public void setErrorOnReset(boolean errorOnReset) {
715:                this .errorOnReset = errorOnReset;
716:            }
717:
718:            /* (non-Javadoc)
719:             * @see com.ibm.icu.dev.test.util.Lockable#isLocked()
720:             */
721:            public boolean isFrozen() {
722:                // TODO Auto-generated method stub
723:                return locked;
724:            }
725:
726:            /* (non-Javadoc)
727:             * @see com.ibm.icu.dev.test.util.Lockable#lock()
728:             */
729:            public Object freeze() {
730:                locked = true;
731:                return this ;
732:            }
733:
734:            static final boolean DEBUG_WRITE = false;
735:
736:            // TODO Fix to serialize more than just strings.
737:            // Only if all the items are strings will we do the following compression
738:            // Otherwise we'll just use Java Serialization, bulky as it is
739:            public void writeExternal(ObjectOutput out1) throws IOException {
740:                DataOutputCompressor sc = new DataOutputCompressor(out1);
741:                // if all objects are strings
742:                Collection availableValues = getAvailableValues();
743:                boolean allStrings = allAreString(availableValues);
744:                sc.writeBoolean(allStrings);
745:                Map object_index = new LinkedHashMap();
746:                if (allAreString(availableValues)) {
747:                    sc.writeStringSet(new TreeSet(availableValues),
748:                            object_index);
749:                } else {
750:                    sc.writeCollection(availableValues, object_index);
751:                }
752:                sc.writeUInt(length);
753:                int lastTransition = -1;
754:                int lastValueNumber = 0;
755:                if (DEBUG_WRITE)
756:                    System.out.println("Trans count: " + length);
757:                for (int i = 0; i < length; ++i) {
758:                    int valueNumber = ((Integer) object_index.get(values[i]))
759:                            .intValue();
760:                    if (DEBUG_WRITE)
761:                        System.out.println("Trans: " + transitions[i] + ",\t"
762:                                + valueNumber);
763:
764:                    int deltaTransition = transitions[i] - lastTransition;
765:                    lastTransition = transitions[i];
766:                    int deltaValueNumber = valueNumber - lastValueNumber;
767:                    lastValueNumber = valueNumber;
768:
769:                    deltaValueNumber <<= 1; // make room for one bit
770:                    boolean canCombine = deltaTransition == 1;
771:                    if (canCombine)
772:                        deltaValueNumber |= 1;
773:                    sc.writeInt(deltaValueNumber);
774:                    if (DEBUG_WRITE)
775:                        System.out.println("deltaValueNumber: "
776:                                + deltaValueNumber);
777:                    if (!canCombine) {
778:                        sc.writeUInt(deltaTransition);
779:                        if (DEBUG_WRITE)
780:                            System.out.println("deltaTransition: "
781:                                    + deltaTransition);
782:                    }
783:                }
784:                sc.flush();
785:            }
786:
787:            /**
788:             * 
789:             */
790:            private boolean allAreString(Collection availableValues2) {
791:                //if (true) return false;
792:                for (Iterator it = availableValues2.iterator(); it.hasNext();) {
793:                    if (!(it.next() instanceof  String))
794:                        return false;
795:                }
796:                return true;
797:            }
798:
799:            public void readExternal(ObjectInput in1) throws IOException,
800:                    ClassNotFoundException {
801:                DataInputCompressor sc = new DataInputCompressor(in1);
802:                boolean allStrings = sc.readBoolean();
803:                Object[] valuesList;
804:                availableValues = new LinkedHashSet();
805:                if (allStrings) {
806:                    valuesList = sc.readStringSet(availableValues);
807:                } else {
808:                    valuesList = sc.readCollection(availableValues);
809:                }
810:                length = sc.readUInt();
811:                transitions = new int[length];
812:                if (DEBUG_WRITE)
813:                    System.out.println("Trans count: " + length);
814:                values = new Object[length];
815:                int currentTransition = -1;
816:                int currentValue = 0;
817:                int deltaTransition;
818:                for (int i = 0; i < length; ++i) {
819:                    int temp = sc.readInt();
820:                    if (DEBUG_WRITE)
821:                        System.out.println("deltaValueNumber: " + temp);
822:                    boolean combined = (temp & 1) != 0;
823:                    temp >>= 1;
824:                    values[i] = valuesList[currentValue += temp];
825:                    if (!combined) {
826:                        deltaTransition = sc.readUInt();
827:                        if (DEBUG_WRITE)
828:                            System.out.println("deltaTransition: "
829:                                    + deltaTransition);
830:                    } else {
831:                        deltaTransition = 1;
832:                    }
833:                    transitions[i] = currentTransition += deltaTransition; // delta value
834:                    if (DEBUG_WRITE)
835:                        System.out.println("Trans: " + transitions[i] + ",\t"
836:                                + currentValue);
837:                }
838:            }
839:
840:            /**
841:             * 
842:             */
843:            static int findCommon(String last, String s) {
844:                int minLen = Math.min(last.length(), s.length());
845:                for (int i = 0; i < minLen; ++i) {
846:                    if (last.charAt(i) != s.charAt(i))
847:                        return i;
848:                }
849:                return minLen;
850:            }
851:
852:            //    /**
853:            //     * @param sc
854:            //     * @throws IOException
855:            //     * 
856:            //     */
857:            //    private void showSize(String title, ObjectOutput out, StreamCompressor sc) throws IOException {
858:            //        sc.showSize(this, title, out);
859:            //    }
860:            //    //public void readObject(ObjectInputStream in) throws IOException {
861:            //    public static class StreamCompressor {
862:            //    	transient byte[] buffer = new byte[1];
863:            //        transient StringBuffer stringBuffer = new StringBuffer();
864:            //        
865:            //        transient byte[] readWriteBuffer = new byte[8];
866:            //        int position = 0;
867:            //        DataOutput out;
868:            //        DataInput in;
869:            //
870:            //        /**
871:            //         * Format is:
872:            //         * @throws IOException
873:            //         */
874:            //        public void writeInt(int i) throws IOException {
875:            //            while (true) {
876:            //                if (position == readWriteBuffer.length) {
877:            //                	out.write(readWriteBuffer);
878:            //                    position = 0;
879:            //                }
880:            //            	if ((i & ~0x7F) == 0) {
881:            //                    readWriteBuffer[position++] = (byte)i;
882:            //                    break;
883:            //                }
884:            //                readWriteBuffer[position++] = (byte)(0x80 | i);
885:            //                i >>>= 7;
886:            //            }
887:            //        }
888:            //		/**
889:            //		 * @throws IOException
890:            //		 * 
891:            //		 */
892:            //		public int readNInt(ObjectInput in) throws IOException {
893:            //			int result = readInt(in);
894:            //            boolean negative = (result & 1) != 0;
895:            //            result >>>= 1;
896:            //            if (negative) result = ~result;
897:            //            return result;
898:            //		}
899:            //		/**
900:            //		 * @throws IOException
901:            //		 * 
902:            //		 */
903:            //		public void writeNInt(int input) throws IOException {
904:            //            int flag = 0;
905:            //            if (input < 0) {
906:            //                input = ~input;
907:            //                flag = 1;
908:            //            }
909:            //			input = (input << 1) | flag;
910:            //			writeInt(out, input);
911:            //		}
912:            //		/**
913:            //		 * @throws IOException
914:            //		 * 
915:            //		 */
916:            //		public void flush() throws IOException {
917:            //            out.write(readWriteBuffer);
918:            //            position = 0;
919:            //		}
920:            //        
921:            //        int readPosition = readWriteBuffer.length;
922:            //        
923:            //		public int readInt(ObjectInput in) throws IOException {
924:            //            int result = 0;
925:            //            int offset = 0;
926:            //            while (true) {
927:            //                if (readPosition == readWriteBuffer.length) {
928:            //                	in.read(readWriteBuffer);
929:            //                    readPosition = 0;
930:            //                }
931:            //                //in.read(buffer);
932:            //                int input = readWriteBuffer[readPosition++]; // buffer[0];
933:            //                result |= (input & 0x7F) << offset;
934:            //                if ((input & 0x80) == 0) {
935:            //                    return result;
936:            //                }
937:            //                offset += 7;
938:            //            }  
939:            //        }
940:            //
941:            //        /**
942:            //         * @throws IOException
943:            //         * 
944:            //         */
945:            //        public void writeString(String s) throws IOException {
946:            //            writeInt(UTF16.countCodePoint(s));
947:            //            writeCodePoints(s);
948:            //        }
949:            //        /**
950:            //		 * 
951:            //		 */
952:            //		private void writeCodePoints(String s) throws IOException {
953:            //			int cp = 0;
954:            //            for (int i = 0; i < s.length(); i += UTF16.getCharCount(cp)) {
955:            //                cp = UTF16.charAt(s, i);
956:            //                writeInt(cp);
957:            //            }
958:            //		}
959:            //		/**
960:            //         * @throws IOException
961:            //         * 
962:            //         */
963:            //        public String readString() throws IOException {
964:            //            int len = readInt(in);
965:            //            return readCodePoints(in, len);
966:            //        }
967:            //		/**
968:            //		 * 
969:            //		 */
970:            //		private String readCodePoints(int len) throws IOException {
971:            //			stringBuffer.setLength(0);
972:            //            for (int i = 0; i < len; ++i) {
973:            //            	int cp = readInt(in);
974:            //                UTF16.append(stringBuffer, cp);
975:            //            }
976:            //            return stringBuffer.toString();
977:            //		}
978:            //		/**
979:            //		 * @param this
980:            //		 * @throws IOException
981:            //		 * 
982:            //		 */
983:            //		private void showSize(UnicodeMap map, String title, ObjectOutput out) throws IOException {
984:            //		    out.flush();
985:            //			System.out.println(title + ": " + (map.debugOut.size() + position));
986:            //		}
987:            //    }
988:        }
989:        //#endif
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.