Source Code Cross Referenced for DocCache.java in  » Swing-Library » abeille-forms-designer » org » netbeans » editor » 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 » Swing Library » abeille forms designer » org.netbeans.editor 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         *                 Sun Public License Notice
0003:         * 
0004:         * The contents of this file are subject to the Sun Public License
0005:         * Version 1.0 (the "License"). You may not use this file except in
0006:         * compliance with the License. A copy of the License is available at
0007:         * http://www.sun.com/
0008:         * 
0009:         * The Original Code is NetBeans. The Initial Developer of the Original
0010:         * Code is Sun Microsystems, Inc. Portions Copyright 1997-2000 Sun
0011:         * Microsystems, Inc. All Rights Reserved.
0012:         */
0013:
0014:        package org.netbeans.editor;
0015:
0016:        import javax.swing.text.BadLocationException;
0017:
0018:        /**
0019:         * Document cache The cache is used to perform insert/remove/read/find
0020:         * operations over the document. The document data are partly stored in cache
0021:         * fragments and partly in cache support. Cache can contain several
0022:         * non-overlapping fragments. At all times there is one fragment called default
0023:         * fragment. It's used for all operations of callers that don't pass valid
0024:         * fragment information to the insert/remove and other methods.
0025:         * 
0026:         * @author Miloslav Metelka
0027:         * @version 1.00
0028:         */
0029:
0030:        class DocCache {
0031:
0032:            /**
0033:             * Old contents of the fragment will be reused if backward overlapping is at
0034:             * least this len
0035:             */
0036:            private static final int MIN_FRAGMENT_BACK_OVERLAP_LEN = 256;
0037:
0038:            /**
0039:             * CacheSupport that this cache uses. Cache support holds the whole
0040:             * document. There are two obvious storages - char array held in memory and
0041:             * file based storage. When there are changes made to the cache, they are
0042:             * held in fragments of the cache until they become so big that they must be
0043:             * flushed to the support.
0044:             */
0045:            private DocCacheSupport support;
0046:
0047:            /** Array of all fragments that this cache uses */
0048:            private Fragment[] frags;
0049:
0050:            /**
0051:             * Default fragment. It is used when null is passed as segment to
0052:             * insert/remove and other operations. It's also used when docLen is 0 to be
0053:             * the only one fragment available for insertion.
0054:             */
0055:            private Fragment defFrag;
0056:
0057:            /**
0058:             * Direct mode allowing to forward all operations directly to cache support.
0059:             * This is useful when support is memory based. No cache fragments are
0060:             * created for direct mode to save memory.
0061:             */
0062:            private boolean directMode;
0063:
0064:            /**
0065:             * Document length difference of all the fragments against the length of
0066:             * document that is given by support document len. Formula: support document
0067:             * len + docLenDelta = total document len
0068:             */
0069:            private int docLenDelta = 0;
0070:
0071:            /* Statistics */
0072:            public int statRead = 0;
0073:            public int statInsert = 0;
0074:            public int statRemove = 0;
0075:            public int statReadFragCnt = 0;
0076:            public int statWriteFragCnt = 0;
0077:            public int statOverlapCnt = 0;
0078:            public int statBackOverlapCnt = 0;
0079:            public int statFragSwitchCnt = 0;
0080:            public int statFragSetEmpty = 0;
0081:
0082:            /**
0083:             * Create the new cache with the specified size of default fragment.
0084:             * 
0085:             * @param support
0086:             *            CacheSupport to use for the document
0087:             * @param len
0088:             *            Length of the default fragment
0089:             * @param directMode
0090:             *            whether all operations should be routed to support
0091:             */
0092:            public DocCache(DocCacheSupport support, int len, boolean directMode) {
0093:                this .support = support;
0094:                if (directMode && !support.supportsDirectMode()) {
0095:                    directMode = false;
0096:                }
0097:                this .directMode = directMode;
0098:                if (!directMode) {
0099:                    defFrag = addFragment(len);
0100:                }
0101:            }
0102:
0103:            /**
0104:             * Set initial content of the cache. This function may be called only once,
0105:             * after construction, before the data in cache are read or manipulated.
0106:             * Otherwise the cache content will be damaged. The reason for using this
0107:             * function is that content that's read from reader and that should be put
0108:             * into support can be also put directly into cache which saves whole
0109:             * support read.
0110:             * 
0111:             * @param initCache
0112:             *            initial cache data
0113:             * @param offset
0114:             *            first valid offset in initial cache
0115:             * @param cacheLen
0116:             *            length of data initial cache
0117:             */
0118:            void initCacheContent(char initCache[], int offset, int cacheLen) {
0119:                if (directMode) {
0120:                    return;
0121:                }
0122:                if (initCache != null) {
0123:                    defFrag.fragLen = Math.min(defFrag.buffer.length, cacheLen
0124:                            - offset);
0125:                    defFrag.origLen = defFrag.fragLen;
0126:                    System.arraycopy(initCache, offset, defFrag.buffer, 0,
0127:                            defFrag.fragLen);
0128:                    defFrag.startPos = 0;
0129:                }
0130:            }
0131:
0132:            public synchronized Fragment addFragment(int fragLen) {
0133:                if (directMode) {
0134:                    return null;
0135:                }
0136:                Fragment f = new Fragment(fragLen);
0137:                if (frags != null) {
0138:                    Fragment[] tmpFrags = new Fragment[frags.length + 1];
0139:                    System.arraycopy(frags, 0, tmpFrags, 0, frags.length);
0140:                    tmpFrags[frags.length] = f;
0141:                    frags = tmpFrags;
0142:                } else {
0143:                    frags = new Fragment[1];
0144:                    frags[0] = f;
0145:                }
0146:                return f;
0147:            }
0148:
0149:            /** Flush the whole cache to support */
0150:            public synchronized void flush() {
0151:                if (directMode) {
0152:                    return;
0153:                }
0154:                for (int i = 0; i < frags.length; i++) {
0155:                    if (frags[i].valid) {
0156:                        frags[i].write();
0157:                    }
0158:                }
0159:            }
0160:
0161:            /**
0162:             * Read fragment and ensure that specified position will be inside (or at
0163:             * the end) of the fragment's cache.
0164:             * 
0165:             * @param frag
0166:             *            fragment to read
0167:             * @param pos
0168:             *            position that must be inside the fragment
0169:             */
0170:            private void readFrag(Fragment frag, int pos) {
0171:                int len; // len of chars to be read
0172:                Fragment f;
0173:
0174:                if (frag.modified) {
0175:                    frag.write(); // flush this fragment if modified
0176:                }
0177:
0178:                int mantLow = 0, mantHigh = getDocLenImpl(); // mantinels
0179:                int csDelta = 0;
0180:                int i;
0181:                for (i = 0; i < frags.length; i++) {
0182:                    f = frags[i];
0183:                    if (f.valid && f != frag) {
0184:                        if (f.startPos > pos) {
0185:                            mantHigh = f.startPos;
0186:                            break;
0187:                        } else {
0188:                            csDelta += f.origLen - f.fragLen;
0189:                            mantLow = f.startPos + f.fragLen;
0190:                        }
0191:                    }
0192:                }
0193:
0194:                // count position from which should be read
0195:                pos = Math.max(pos - frag.buffer.length / 2, mantLow);
0196:                len = Math.min(mantHigh - pos, frag.buffer.length);
0197:                frag.read(pos, len, csDelta);
0198:
0199:                // repair the fragment's position in frags
0200:                if (i == frags.length
0201:                        || (frags[i] != frag && (i == 0 || frags[i - 1] != frag))) {
0202:                    statFragSwitchCnt++;
0203:                    int fragInd;
0204:                    for (fragInd = 0; fragInd < frags.length; fragInd++) {
0205:                        if (frags[fragInd] == frag) {
0206:                            break;
0207:                        }
0208:                    }
0209:                    if (fragInd < i) { // frag before i
0210:                        for (int j = fragInd + 1; j < i; j++) {
0211:                            frags[j - 1] = frags[j];
0212:                        }
0213:                        frags[i - 1] = frag;
0214:                    } else { // frag after i
0215:                        for (int j = fragInd; j > i; j--) {
0216:                            frags[j] = frags[j - 1];
0217:                        }
0218:                        frags[i] = frag;
0219:                    }
0220:                }
0221:                frag.valid = true;
0222:            }
0223:
0224:            /**
0225:             * Get the correct fragment for a given position. Search all the fragments
0226:             * if there's one that contains given position. If not get or create
0227:             * optional fragment and read into it.
0228:             * 
0229:             * @param pos
0230:             *            position that the fragment should contain
0231:             * @param frag
0232:             *            current fragment
0233:             * @param wantInsert
0234:             *            want to perform insert on got fragment
0235:             * @return fragment that will contain position
0236:             */
0237:            private Fragment getFrag(int pos, Fragment frag, boolean wantInsert) {
0238:                Fragment f;
0239:                for (int i = 0; i < frags.length; i++) {
0240:                    f = frags[i];
0241:                    if (f.valid) {
0242:                        if (wantInsert) {
0243:                            if (f.isIn(pos)) {
0244:                                if (pos == f.startPos + f.fragLen) { // right at the
0245:                                    // end of frag
0246:                                    i++;
0247:                                    while (i < frags.length) {
0248:                                        if (frags[i].valid) {
0249:                                            if (frags[i].startPos == pos) { // successive
0250:                                                // frag
0251:                                                f = frags[i];
0252:                                                break;
0253:                                            }
0254:                                        }
0255:                                        i++;
0256:                                    }
0257:                                }
0258:                                // test if fragment full for insertions
0259:                                if (f.modified && f.lastMod == f.buffer.length) {
0260:                                    readFrag(f, pos);
0261:                                }
0262:                                return f;
0263:                            }
0264:                        } else {
0265:                            if (f.isInside(pos)) {
0266:                                return f;
0267:                            }
0268:                        }
0269:                    }
0270:                }
0271:
0272:                // check for zero document len
0273:                if (getDocLenImpl() == 0) { // should be just for inserts
0274:                    for (int i = 0; i < frags.length; i++) {
0275:                        f = frags[i];
0276:                        if (f.valid) {
0277:                            return f; // in fact there should be any valid
0278:                        }
0279:                    }
0280:                    // no valid fragment, make defFrag active
0281:                    defFrag.setEmptyValid();
0282:                    return defFrag;
0283:                }
0284:
0285:                // get the fragment and read into it
0286:                if (frag != null) {
0287:                    f = frag.actFrag = frag;
0288:                } else {
0289:                    f = defFrag;
0290:                }
0291:                readFrag(f, pos);
0292:                return f;
0293:            }
0294:
0295:            /**
0296:             * Update starting positions of all fragments that have higher start
0297:             * positions than the given one
0298:             * 
0299:             * @param frag
0300:             *            fragment that will not be updated
0301:             * @param pos
0302:             *            position over which the fragments will be updated
0303:             * @param delta
0304:             *            how much increase/decrease starting positions
0305:             */
0306:            private void updateStartPos(Fragment frag, int pos, int delta) {
0307:                for (int i = frags.length - 1; i >= 0; i--) {
0308:                    Fragment f = frags[i];
0309:                    if (f.valid) {
0310:                        if (f.startPos >= pos) {
0311:                            if (f != frag) {
0312:                                f.startPos += delta;
0313:                            }
0314:                        } else {
0315:                            break; // reached lowest position
0316:                        }
0317:                    }
0318:                }
0319:            }
0320:
0321:            /**
0322:             * Insert the array of chars at some position. It can be done in one or more
0323:             * cycles.
0324:             * 
0325:             * @param pos
0326:             *            from which position
0327:             * @param text
0328:             *            text to insert
0329:             * @param frag
0330:             *            dedicated fragment (can be null)
0331:             */
0332:            public synchronized void insert(int pos, char text[], Fragment frag)
0333:                    throws BadLocationException {
0334:                if (pos < 0 || pos > getDocLenImpl()) {
0335:                    throwPosException(pos);
0336:                }
0337:                int restLen = text.length; // rest of len to insert
0338:                if (restLen == 0) {
0339:                    return;
0340:                }
0341:                if (directMode) {
0342:                    support.insert(pos, text, 0, restLen);
0343:                    return;
0344:                }
0345:                int wrLen; // write len in one cycle
0346:                int bufPos; // relative position from the start of cache
0347:                int moveLen; // how much data will be moved inside cache to make
0348:                // space
0349:                Fragment f = (frag == null) ? defFrag : frag.actFrag;
0350:                boolean bufOK = false;
0351:                if (f.isInside(pos)
0352:                        && (!f.modified || f.lastMod < f.buffer.length)) {
0353:                    bufOK = true; // pos inside and buffer not full for insertion
0354:                }
0355:
0356:                while (restLen > 0) { // till all the data will be inserted
0357:                    // is pos in current fragment
0358:                    if (bufOK) {
0359:                        bufOK = false;
0360:                    } else {
0361:                        f = getFrag(pos, frag, true); // get fragment for inserting
0362:                    }
0363:                    bufPos = pos - f.startPos;
0364:                    if (!f.modified) {
0365:                        f.modified = true;
0366:                        f.firstMod = f.lastMod = bufPos;
0367:                    }
0368:                    wrLen = f.buffer.length - Math.max(bufPos, f.lastMod);
0369:                    wrLen = Math.min(wrLen, restLen);
0370:                    // find how many bytes should be moved inside the cache
0371:                    moveLen = Math.min(f.fragLen - bufPos, f.buffer.length
0372:                            - (bufPos + wrLen));
0373:                    if (moveLen > 0) { // now make space for inserted data
0374:                        System.arraycopy(f.buffer, bufPos, f.buffer, bufPos
0375:                                + wrLen, moveLen);
0376:                    }
0377:                    // move the data from text array to the cache
0378:                    System.arraycopy(text, text.length - restLen, f.buffer,
0379:                            bufPos, wrLen);
0380:                    f.updatePos(bufPos, wrLen); // correct positions in the fragment
0381:                    docLenDelta += wrLen;
0382:                    if (frags.length > 1) {
0383:                        updateStartPos(f, pos, wrLen); // correct positions of other
0384:                        // frags
0385:                    }
0386:                    restLen -= wrLen;
0387:                    pos += wrLen;
0388:                }
0389:
0390:                if (frag != null) {
0391:                    frag.actFrag = f;
0392:                }
0393:                statInsert += text.length; // update insert statistics
0394:            }
0395:
0396:            /**
0397:             * Insert the string at some position. It can be done in one or more cycles.
0398:             * 
0399:             * @param pos
0400:             *            from which position
0401:             * @param text
0402:             *            text to insert
0403:             * @param frag
0404:             *            dedicated fragment (can be null)
0405:             */
0406:            public synchronized void insertString(int pos, String text,
0407:                    Fragment frag) throws BadLocationException {
0408:                if (pos < 0 || pos > getDocLenImpl()) {
0409:                    throwPosException(pos);
0410:                }
0411:                int textLen = text.length();
0412:                int restLen = textLen; // rest of len to insert
0413:                if (restLen == 0) {
0414:                    return;
0415:                }
0416:                if (directMode) {
0417:                    support.insertString(pos, text, 0, restLen);
0418:                    return;
0419:                }
0420:                int wrLen; // write len in one cycle
0421:                int bufPos; // relative position from the start of cache
0422:                int moveLen; // how much data will be moved inside cache to make
0423:                // space
0424:                Fragment f = (frag == null) ? defFrag : frag.actFrag;
0425:                boolean bufOK = false;
0426:                if (f.isInside(pos)
0427:                        && (!f.modified || f.lastMod < f.buffer.length)) {
0428:                    bufOK = true; // pos inside and buffer not full for insertion
0429:                }
0430:
0431:                while (restLen > 0) { // till all the data will be inserted
0432:                    // is pos in current fragment
0433:                    if (bufOK) {
0434:                        bufOK = false;
0435:                    } else {
0436:                        f = getFrag(pos, frag, true); // get fragment for inserting
0437:                    }
0438:                    bufPos = pos - f.startPos;
0439:                    if (!f.modified) {
0440:                        f.modified = true;
0441:                        f.firstMod = f.lastMod = bufPos;
0442:                    }
0443:                    wrLen = f.buffer.length - Math.max(bufPos, f.lastMod);
0444:                    wrLen = Math.min(wrLen, restLen);
0445:                    // find how many bytes should be moved inside the cache
0446:                    moveLen = Math.min(f.fragLen - bufPos, f.buffer.length
0447:                            - (bufPos + wrLen));
0448:                    if (moveLen > 0) { // now make space for inserted data
0449:                        System.arraycopy(f.buffer, bufPos, f.buffer, bufPos
0450:                                + wrLen, moveLen);
0451:                    }
0452:                    // move the data from text to the cache
0453:                    text.getChars(textLen - restLen, textLen - restLen + wrLen,
0454:                            f.buffer, bufPos);
0455:                    f.updatePos(bufPos, wrLen); // correct positions in the fragment
0456:                    docLenDelta += wrLen;
0457:                    if (frags.length > 1) {
0458:                        updateStartPos(f, pos, wrLen); // correct positions of other
0459:                        // frags
0460:                    }
0461:                    restLen -= wrLen;
0462:                    pos += wrLen;
0463:                }
0464:
0465:                if (frag != null) {
0466:                    frag.actFrag = f;
0467:                }
0468:                statInsert += textLen; // update insert statistics
0469:            }
0470:
0471:            /**
0472:             * Remove the specified count of chars from the specified position.
0473:             * 
0474:             * @param pos
0475:             *            position from which remove the text
0476:             * @param len
0477:             *            length of the data to be removed
0478:             * @param frag
0479:             *            dedicated fragment (can be null)
0480:             * @returns the removed text
0481:             */
0482:            public synchronized void remove(int pos, int len, Fragment frag)
0483:                    throws BadLocationException {
0484:                int removeLen; // remove length inside the cache
0485:                int restLen = len; // remaining len to remove
0486:                int bufPos;
0487:                if (len == 0) {
0488:                    return;
0489:                }
0490:                if (pos < 0) {
0491:                    throwPosException(pos);
0492:                }
0493:                if (pos + len > getDocLenImpl()) {
0494:                    throwPosException(pos + len);
0495:                }
0496:                if (directMode) {
0497:                    support.remove(pos, len);
0498:                    return;
0499:                }
0500:
0501:                // get the fragment
0502:                Fragment f = (frag == null) ? defFrag : frag.actFrag;
0503:                // first check if the removed block is fully in the cache
0504:                if (pos < 0 || pos + len > f.startPos + f.fragLen) {
0505:                    // test position correctness
0506:                }
0507:
0508:                while (restLen > 0) {
0509:                    // get the correct fragment
0510:                    if (!f.isInside(pos)) {
0511:                        f = getFrag(pos, f, false);
0512:                    }
0513:                    // get the positions
0514:                    bufPos = pos - f.startPos;
0515:                    removeLen = Math.min(restLen, f.fragLen - bufPos);
0516:                    System.arraycopy(f.buffer, bufPos + removeLen, f.buffer,
0517:                            bufPos, f.fragLen - (bufPos + removeLen));
0518:                    if (!f.modified) {
0519:                        f.modified = true;
0520:                        f.firstMod = f.lastMod = bufPos;
0521:                    }
0522:                    f.updatePos(bufPos, -removeLen);
0523:                    docLenDelta -= removeLen;
0524:                    if (frags.length > 1) {
0525:                        updateStartPos(f, pos, -removeLen); // correct positions of
0526:                        // other frags
0527:                    }
0528:                    restLen -= removeLen;
0529:                }
0530:
0531:                if (frag != null) {
0532:                    frag.actFrag = f;
0533:                }
0534:                statRemove += len;
0535:            }
0536:
0537:            /**
0538:             * Read the data from the cache. Output array must be provided.
0539:             * 
0540:             * @param pos
0541:             *            position from which read starts
0542:             * @param ret
0543:             *            char array where the data should be put. There must be enough
0544:             *            space in array to hold len requested characters
0545:             * @param offset
0546:             *            offset in return array where data will be written
0547:             * @param len
0548:             *            len to read
0549:             * @param frag
0550:             *            dedicated fragment (can be null)
0551:             */
0552:            public synchronized void read(int pos, char ret[], int offset,
0553:                    int len, Fragment frag) throws BadLocationException {
0554:                if (pos < 0 || len < 0) {
0555:                    throwPosException(pos);
0556:                }
0557:                if (pos + len > getDocLenImpl()) {
0558:                    throwPosException(pos + len);
0559:                }
0560:                if (directMode) {
0561:                    support.read(pos, ret, offset, len);
0562:                    return;
0563:                }
0564:                int getLen, bufPos;
0565:                int restLen = len; // the rest to retrieve
0566:                // get the fragment
0567:                Fragment f = (frag == null) ? defFrag : frag.actFrag;
0568:                while (restLen > 0) {
0569:                    // check if pos is inside fragment
0570:                    if (!f.isInside(pos)) {
0571:                        f = getFrag(pos, frag, false);
0572:                    }
0573:                    bufPos = pos - f.startPos; // position in cache
0574:                    getLen = Math.min(f.fragLen - bufPos, restLen);
0575:                    // copy into return array
0576:                    System.arraycopy(f.buffer, bufPos, ret, len - restLen
0577:                            + offset, getLen);
0578:                    pos += getLen;
0579:                    restLen -= getLen;
0580:                }
0581:
0582:                if (frag != null) {
0583:                    frag.actFrag = f;
0584:                }
0585:                statRead += len;
0586:            }
0587:
0588:            /**
0589:             * Read the data from the cache and return reults as char array.
0590:             * 
0591:             * @param pos
0592:             *            position from which read starts
0593:             * @param len
0594:             *            len to read
0595:             * @param frag
0596:             *            dedicated fragment (can be null)
0597:             * @return char array with data from document
0598:             */
0599:            public final char[] read(int pos, int len, Fragment frag)
0600:                    throws BadLocationException {
0601:                if (len < 0) {
0602:                    throwPosException(pos);
0603:                }
0604:                char ret[] = new char[len];
0605:                read(pos, ret, 0, len, frag);
0606:                return ret;
0607:            }
0608:
0609:            /**
0610:             * Find something in the cache using specified <CODE>Finder</CODE>. It
0611:             * covers both forward and backward searches. To do backward search, specify
0612:             * endPos < startPos. The following position intervals are searched: forward
0613:             * search: <startPos, endPos) - from startPos to endPos - 1 backward search:
0614:             * <endPos, startPos) - from startPos - 1 to endPos Both startPos and endPos
0615:             * can be -1 to indicate end of document position
0616:             * 
0617:             * @param finder
0618:             *            finder that will be used for searching
0619:             * @param startPos
0620:             *            position from which search starts. For backward search this
0621:             *            value is greater or equal than <CODE>endPos</CODE>.
0622:             * @param endPos
0623:             *            limit position of search area For backward search this value
0624:             *            is lower than <CODE>startPos</CODE>.
0625:             * @param frag
0626:             *            dedicated fragment (can be null)
0627:             * @return position where the found string begins or -1 if the text was not
0628:             *         found
0629:             */
0630:            public synchronized int find(Finder finder, int startPos,
0631:                    int endPos, Fragment frag) throws BadLocationException {
0632:                int docLen = getDocLenImpl();
0633:                if (startPos == -1) {
0634:                    startPos = docLen;
0635:                }
0636:                if (endPos == -1) {
0637:                    endPos = docLen;
0638:                }
0639:
0640:                // check bounds
0641:                if (startPos < 0 || startPos > docLen) {
0642:                    throwPosException(startPos);
0643:                }
0644:                if (endPos < 0 || endPos > docLen) {
0645:                    throwPosException(endPos);
0646:                }
0647:
0648:                finder.reset(); // initialize finder
0649:                if (startPos == endPos) { // immediate return for void search
0650:                    return -1;
0651:                }
0652:                boolean forward = (startPos < endPos);
0653:                int pos = forward ? startPos : (startPos - 1);
0654:
0655:                if (directMode) {
0656:                    while (true) {
0657:                        pos = finder.find(0, support.getDirectModeBuffer(),
0658:                                forward ? startPos : endPos, forward ? endPos
0659:                                        : startPos, pos, endPos);
0660:
0661:                        if (finder.isFound()) {
0662:                            if (forward) {
0663:                                if (pos < startPos || pos > endPos) {
0664:                                    return -1; // invalid position returned
0665:                                }
0666:                            } else { // searching backward
0667:                                if (pos < endPos || pos > startPos) {
0668:                                    return -1; // invalid position returned
0669:                                }
0670:                            }
0671:                            return pos;
0672:
0673:                        } else { // not yet found
0674:
0675:                            // Check position correctness. It eliminates
0676:                            // also the equalities because the empty buffer
0677:                            // would be pzssed in these cases to the finder
0678:                            if (forward) { // searching forward
0679:                                if (pos < startPos || pos >= endPos) {
0680:                                    return -1;
0681:                                }
0682:                            } else { // searching backward
0683:                                if (pos < endPos || pos >= startPos) {
0684:                                    return -1; // not found
0685:                                }
0686:                            }
0687:                        }
0688:                    }
0689:                }
0690:                // get the fragment
0691:                Fragment f = (frag == null) ? defFrag : frag.actFrag;
0692:                while (true) {
0693:                    // check if pos is inside fragment
0694:                    if (!f.isInside(pos)) {
0695:                        f = getFrag(pos, frag, false);
0696:                    }
0697:                    int offset1 = Math.max(forward ? startPos : endPos,
0698:                            f.startPos)
0699:                            - f.startPos;
0700:                    int offset2 = Math.min(forward ? endPos : startPos,
0701:                            f.startPos + f.fragLen)
0702:                            - f.startPos;
0703:
0704:                    pos = finder.find(f.startPos, f.buffer, offset1, offset2,
0705:                            pos, endPos);
0706:
0707:                    // check found position correctness
0708:                    if (finder.isFound()) {
0709:                        if (forward) {
0710:                            if (pos < startPos || pos > endPos) {
0711:                                return -1; // invalid position returned
0712:                            }
0713:                        } else { // searching backward
0714:                            if (pos < endPos || pos > startPos) {
0715:                                return -1; // invalid position returned
0716:                            }
0717:                        }
0718:                        break;
0719:
0720:                    } else { // not yet found
0721:                        // Check position correctness. It eliminates
0722:                        // also the equalities because the empty buffer
0723:                        // would be pzssed in these cases to the finder
0724:                        if (forward) { // searching forward
0725:                            if (pos < startPos || pos >= endPos) {
0726:                                return -1;
0727:                            }
0728:                        } else { // searching backward
0729:                            if (pos < endPos || pos >= startPos) {
0730:                                return -1; // not found
0731:                            }
0732:                        }
0733:                    }
0734:                }
0735:
0736:                if (frag != null) {
0737:                    frag.actFrag = f;
0738:                }
0739:                return pos; // return found position
0740:            }
0741:
0742:            /** Get the total length of the document. */
0743:            public synchronized final int getDocLength() {
0744:                return getDocLenImpl();
0745:            }
0746:
0747:            private int getDocLenImpl() {
0748:                return support.getDocLength() + docLenDelta;
0749:            }
0750:
0751:            /** Fragment of the cache */
0752:            private class Fragment {
0753:
0754:                /** buffer space of the fragment */
0755:                char buffer[];
0756:
0757:                /** Position of the first character cached in the fragment */
0758:                int startPos = -1;
0759:
0760:                /**
0761:                 * Number of chars in the buffer of this fragment. If this value is 0,
0762:                 * it means that the fragment is invalid.
0763:                 */
0764:                int fragLen;
0765:
0766:                /** Original len when the buffer was read */
0767:                int origLen;
0768:
0769:                /** First modified char in the buffer */
0770:                int firstMod;
0771:
0772:                /** Offset of last modified char int the buffer */
0773:                int lastMod;
0774:
0775:                /** Was the buffer modified or not */
0776:                boolean modified;
0777:
0778:                /**
0779:                 * Is this fragment valid? Fragment becomes invalid when it contains no
0780:                 * data.
0781:                 */
0782:                boolean valid;
0783:
0784:                /**
0785:                 * Actual fragment which is either this fragment or when the last search
0786:                 * didn't succeeded in this fragment, some other fragment.
0787:                 */
0788:                Fragment actFrag;
0789:
0790:                /**
0791:                 * Construct new fragment with specified length
0792:                 * 
0793:                 * @param len
0794:                 *            len of the constructed fragment
0795:                 */
0796:                Fragment(int len) {
0797:                    buffer = new char[len];
0798:                    actFrag = this ;
0799:                }
0800:
0801:                /** Is the position inside this fragment? */
0802:                boolean isInside(int pos) {
0803:                    return (pos >= startPos) && (pos < startPos + fragLen);
0804:                }
0805:
0806:                /** Is the position inside or at the end of this fragment? */
0807:                boolean isIn(int pos) {
0808:                    return (pos >= startPos) && (pos <= startPos + fragLen);
0809:                }
0810:
0811:                /** Flush the fragment to support */
0812:                void write() {
0813:                    if (!modified) {
0814:                        return;
0815:                    }
0816:
0817:                    int endModPos = startPos + lastMod; // last modification
0818:                    int writeLen;
0819:
0820:                    // count the support delta
0821:                    int csDelta = 0;
0822:                    for (int i = 0; i < frags.length; i++) {
0823:                        Fragment f = frags[i];
0824:                        if (f.valid) {
0825:                            if (f.startPos >= this .startPos) {
0826:                                break;
0827:                            }
0828:                            csDelta += f.origLen - f.fragLen;
0829:                        }
0830:                    }
0831:
0832:                    try {
0833:                        if (fragLen != origLen) { // will either enlarge or shrink
0834:                            // document
0835:                            int delta = fragLen - origLen;
0836:                            if (delta > 0) { // delta > 0; need to enlarge document
0837:                                support.insert(endModPos - delta + csDelta,
0838:                                        buffer, lastMod - delta, delta);
0839:                                writeLen = lastMod - firstMod - delta;
0840:                            } else { // delta < 0; need to shrink the document
0841:                                support.remove(endModPos + csDelta, -delta);
0842:                                writeLen = lastMod - firstMod;
0843:                            }
0844:                        } else { // delta is zero i.e. length of the buffer is the same
0845:                            writeLen = lastMod - firstMod;
0846:                        }
0847:                        if (writeLen > 0) {
0848:                            try {
0849:                                support.write(startPos + firstMod + csDelta,
0850:                                        buffer, firstMod, writeLen);
0851:                            } catch (BadLocationException e) {
0852:                                if (Boolean
0853:                                        .getBoolean("netbeans.debug.exceptions")) { // NOI18N
0854:                                    e.printStackTrace();
0855:                                }
0856:                            }
0857:                        }
0858:                    } catch (BadLocationException e) {
0859:                        if (Boolean.getBoolean("netbeans.debug.exceptions")) { // NOI18N
0860:                            e.printStackTrace();
0861:                        }
0862:                    }
0863:
0864:                    docLenDelta += origLen - fragLen;
0865:                    origLen = fragLen;
0866:                    modified = false;
0867:                    statWriteFragCnt++;
0868:                }
0869:
0870:                /**
0871:                 * Read the fragment to contain specified position
0872:                 * 
0873:                 * @param pos
0874:                 *            start position
0875:                 * @param len
0876:                 *            length to read
0877:                 * @param csDelta
0878:                 *            delta by which the reading position must be corrected when
0879:                 *            reading through support
0880:                 */
0881:                void read(int pos, int len, int csDelta) {
0882:                    int overlap;
0883:                    if (pos < startPos) { // read position is lower than start of frag
0884:                        overlap = Math.min(pos + len - startPos, fragLen);
0885:                        if (overlap > MIN_FRAGMENT_BACK_OVERLAP_LEN) {
0886:                            statBackOverlapCnt++;
0887:                            System.arraycopy(buffer, 0, buffer, startPos - pos,
0888:                                    overlap);
0889:                            try {
0890:                                support.read(pos + csDelta, buffer, 0, startPos
0891:                                        - pos);
0892:                            } catch (BadLocationException e) {
0893:                                if (Boolean
0894:                                        .getBoolean("netbeans.debug.exceptions")) { // NOI18N
0895:                                    e.printStackTrace();
0896:                                }
0897:                            }
0898:
0899:                            overlap = startPos + overlap; // now overlap means pos of
0900:                            // end of block
0901:                            if (overlap < pos + len) {
0902:                                try {
0903:                                    support.read(startPos + fragLen + csDelta,
0904:                                            buffer, overlap - pos, pos + len
0905:                                                    - overlap);
0906:                                } catch (BadLocationException e) {
0907:                                    if (Boolean
0908:                                            .getBoolean("netbeans.debug.exceptions")) { // NOI18N
0909:                                        e.printStackTrace();
0910:                                    }
0911:                                }
0912:                            }
0913:
0914:                        } else { // no or small overlap
0915:                            try {
0916:                                support.read(pos + csDelta, buffer, 0, len);
0917:                            } catch (BadLocationException e) {
0918:                                if (Boolean
0919:                                        .getBoolean("netbeans.debug.exceptions")) { // NOI18N
0920:                                    e.printStackTrace();
0921:                                }
0922:                            }
0923:                        }
0924:                    } else { // pos >= startPos
0925:                        overlap = startPos + fragLen - pos;
0926:                        if (overlap > 0) { // here any overlap is fine !!!
0927:                            statOverlapCnt++;
0928:                            System.arraycopy(buffer, pos - startPos, buffer, 0,
0929:                                    overlap);
0930:                            try {
0931:                                support.read(pos + overlap + csDelta, buffer,
0932:                                        overlap, len - overlap);
0933:                            } catch (BadLocationException e) {
0934:                                if (Boolean
0935:                                        .getBoolean("netbeans.debug.exceptions")) { // NOI18N
0936:                                    e.printStackTrace();
0937:                                }
0938:                            }
0939:                        } else { // no overlap
0940:                            try {
0941:                                support.read(pos + csDelta, buffer, 0, len);
0942:                            } catch (BadLocationException e) {
0943:                                if (Boolean
0944:                                        .getBoolean("netbeans.debug.exceptions")) { // NOI18N
0945:                                    e.printStackTrace();
0946:                                }
0947:                            }
0948:                        }
0949:                    }
0950:
0951:                    startPos = pos;
0952:                    fragLen = origLen = len;
0953:                    valid = true;
0954:                    statReadFragCnt++;
0955:                }
0956:
0957:                /** Invalidate segment so it will no longer be used for operations */
0958:                void invalidate() {
0959:                    write(); // flush the fragment
0960:                    valid = false;
0961:                    startPos = -1; // important for isIn() and others
0962:                    fragLen = origLen = 0;
0963:                }
0964:
0965:                /**
0966:                 * Set this segment as valid even when it has zero size. It is done only
0967:                 * when total doc len is 0.
0968:                 */
0969:                void setEmptyValid() {
0970:                    statFragSetEmpty++;
0971:                    fragLen = origLen = 0;
0972:                    startPos = 0;
0973:                    valid = true;
0974:                }
0975:
0976:                /**
0977:                 * Update various positions in fragment after modification.
0978:                 * 
0979:                 * @param bufPos
0980:                 *            position in the buffer where the modification was done
0981:                 * @param delta
0982:                 *            of the change
0983:                 */
0984:                void updatePos(int bufPos, int delta) {
0985:                    if (bufPos < firstMod) {
0986:                        firstMod = bufPos;
0987:                    }
0988:
0989:                    if (delta > 0) { // insert was done
0990:                        if (bufPos > lastMod) {
0991:                            lastMod = bufPos + delta;
0992:                        } else {
0993:                            lastMod += delta;
0994:                        }
0995:                        fragLen += delta;
0996:                        if (fragLen > buffer.length) {
0997:                            origLen -= fragLen - buffer.length;
0998:                            fragLen = buffer.length;
0999:                        }
1000:                    } else { // remove was done
1001:                        if (bufPos - delta <= lastMod) { // if whole block below
1002:                            // lastMod
1003:                            lastMod += delta;
1004:                        } else {
1005:                            lastMod = bufPos;
1006:                        }
1007:                        fragLen += delta;
1008:                        if (fragLen == 0) { // empty fragment must be invalidated
1009:                            invalidate();
1010:                        }
1011:                    }
1012:                }
1013:
1014:                public String toString() {
1015:                    int i;
1016:                    for (i = 0; i < frags.length; i++) {
1017:                        if (frags[i] == this ) {
1018:                            break;
1019:                        }
1020:                    }
1021:                    return "Frag[" + i + "] valid=" + valid + ", startPos="
1022:                            + startPos // NOI18N
1023:                            + ", fragLen=" + fragLen + ", origLen=" + origLen // NOI18N
1024:                            + ", fMod=" + firstMod + ", lMod=" + lastMod // NOI18N
1025:                            + ", mod=" + modified; // NOI18N
1026:                }
1027:
1028:            }
1029:
1030:            /** Throw position exception */
1031:            final void throwPosException(int pos) throws BadLocationException {
1032:                throw new BadLocationException("DocCache: Invalid offset "
1033:                        + pos // NOI18N
1034:                        + ". Document length is " + getDocLenImpl(), pos); // NOI18N
1035:            }
1036:
1037:            public String toString() {
1038:                String ret = "support=" + support; // NOI18N
1039:                if (directMode) {
1040:                    ret += ", Direct mode, no fragments\n"; // NOI18N
1041:                } else {
1042:                    ret += ", fragment count=" + frags.length + "\n"; // NOI18N
1043:                    for (int i = 0; i < frags.length; i++) {
1044:                        ret += frags[i] + "\n"; // NOI18N
1045:                    }
1046:                }
1047:
1048:                ret += " getDocLength()=" + getDocLength() + ", docLenDelta="
1049:                        + docLenDelta // NOI18N
1050:                        + ", statRead=" + statRead + ", statInsert=" // NOI18N
1051:                        + statInsert + ", statRemove=" + statRemove // NOI18N
1052:                        + ", statReadFragCnt=" + statReadFragCnt // NOI18N
1053:                        + ", statWriteFragCnt=" + statWriteFragCnt // NOI18N
1054:                        + ", statOverlapCnt=" + statOverlapCnt // NOI18N
1055:                        + ", statBackOverlapCnt=" + statBackOverlapCnt // NOI18N
1056:                        + ", statFragSwitchCnt=" + statFragSwitchCnt // NOI18N
1057:                        + ", statFragSetEmpty=" + statFragSetEmpty; // NOI18N
1058:
1059:                return ret;
1060:            }
1061:
1062:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.