Source Code Cross Referenced for ExtSyntaxSupport.java in  » IDE-Netbeans » editor » org » netbeans » editor » ext » 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 » IDE Netbeans » editor » org.netbeans.editor.ext 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003:         *
004:         * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005:         *
006:         * The contents of this file are subject to the terms of either the GNU
007:         * General Public License Version 2 only ("GPL") or the Common
008:         * Development and Distribution License("CDDL") (collectively, the
009:         * "License"). You may not use this file except in compliance with the
010:         * License. You can obtain a copy of the License at
011:         * http://www.netbeans.org/cddl-gplv2.html
012:         * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013:         * specific language governing permissions and limitations under the
014:         * License.  When distributing the software, include this License Header
015:         * Notice in each file and include the License file at
016:         * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
017:         * particular file as subject to the "Classpath" exception as provided
018:         * by Sun in the GPL Version 2 section of the License file that
019:         * accompanied this code. If applicable, add the following below the
020:         * License Header, with the fields enclosed by brackets [] replaced by
021:         * your own identifying information:
022:         * "Portions Copyrighted [year] [name of copyright owner]"
023:         *
024:         * Contributor(s):
025:         *
026:         * The Original Software is NetBeans. The Initial Developer of the Original
027:         * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
028:         * Microsystems, Inc. All Rights Reserved.
029:         *
030:         * If you wish your version of this file to be governed by only the CDDL
031:         * or only the GPL Version 2, indicate your decision by adding
032:         * "[Contributor] elects to include this software in this distribution
033:         * under the [CDDL or GPL Version 2] license." If you do not indicate a
034:         * single choice of license, a recipient has the option to distribute
035:         * your version of this file under either the CDDL, the GPL Version 2 or
036:         * to extend the choice of license to its licensees as provided above.
037:         * However, if you add GPL Version 2 code and therefore, elected the GPL
038:         * Version 2 license, then the option applies only if the new code is
039:         * made subject to such option by the copyright holder.
040:         */
041:
042:        package org.netbeans.editor.ext;
043:
044:        import java.util.Map;
045:        import java.util.HashMap;
046:        import javax.swing.event.DocumentListener;
047:        import javax.swing.event.DocumentEvent;
048:        import javax.swing.text.BadLocationException;
049:        import javax.swing.text.JTextComponent;
050:        import org.netbeans.editor.BaseDocument;
051:        import org.netbeans.editor.SyntaxSupport;
052:        import org.netbeans.editor.Utilities;
053:        import org.netbeans.editor.TokenProcessor;
054:        import org.netbeans.editor.TokenID;
055:        import org.netbeans.editor.TokenContextPath;
056:        import org.netbeans.editor.TokenItem;
057:        import org.netbeans.editor.SettingsNames;
058:        import org.netbeans.editor.FinderFactory;
059:        import org.netbeans.editor.TextBatchProcessor;
060:        import org.netbeans.editor.Analyzer;
061:
062:        /**
063:         * Support methods for syntax analyzes
064:         *
065:         * @author Miloslav Metelka
066:         * @version 1.00
067:         */
068:
069:        public class ExtSyntaxSupport extends SyntaxSupport {
070:
071:            // used in ExtKit
072:
073:            /** Schedule content update making completion visible. */
074:            public static final int COMPLETION_POPUP = 0;
075:            /** Cancel request without changing completion visibility. */
076:            public static final int COMPLETION_CANCEL = 1;
077:            /** Update content immediatelly if it's currently visible. */
078:            public static final int COMPLETION_REFRESH = 2;
079:            /** Schedule content update if it's currently visible. */
080:            public static final int COMPLETION_POST_REFRESH = 3;
081:            /** Hide completion. */
082:            public static final int COMPLETION_HIDE = 4;
083:
084:            private static final TokenID[] EMPTY_TOKEN_ID_ARRAY = new TokenID[0];
085:
086:            /** Listens for the changes on the document. Children can override
087:             * the documentModified() method to perform some processing.
088:             */
089:            private DocumentListener docL;
090:
091:            /** Map holding the [position, local-variable-map] pairs */
092:            private HashMap localVarMaps = new HashMap();
093:
094:            /** Map holding the [position, global-variable-map] pairs */
095:            private HashMap globalVarMaps = new HashMap();
096:
097:            public ExtSyntaxSupport(BaseDocument doc) {
098:                super (doc);
099:
100:                // Create listener to listen on document changes
101:                docL = new DocumentListener() {
102:                    public void insertUpdate(DocumentEvent evt) {
103:                        documentModified(evt);
104:                    }
105:
106:                    public void removeUpdate(DocumentEvent evt) {
107:                        documentModified(evt);
108:                    }
109:
110:                    public void changedUpdate(DocumentEvent evt) {
111:                    }
112:                };
113:                getDocument().addDocumentListener(docL);
114:            }
115:
116:            /** Get the chain of the tokens for the given block of text.
117:             * The returned chain of token-items reflects the tokens
118:             * as they occur in the text and therefore the first token
119:             * can start at the slightly lower position than the requested one.
120:             * The chain itself can be extended automatically when
121:             * reaching the first chain item and calling <tt>getPrevious()</tt>
122:             * on it. Another chunk of the tokens will be parsed and
123:             * the head of the chain will be extended. However this happens
124:             * only in case there was no modification performed to the document
125:             * between the creation of the chain and this moment. Otherwise
126:             * this call throws <tt>IllegalStateException</tt>.
127:             * 
128:             * @param startOffset starting position of the block
129:             * @param endOffset ending position of the block
130:             * @return the first item of the token-item chain or null if there are
131:             *  no tokens in the given area or the area is so small that it lays
132:             *  inside one token. To prevent this provide the area that spans a new-line.
133:             */
134:            public TokenItem getTokenChain(int startOffset, int endOffset)
135:                    throws BadLocationException {
136:
137:                if (startOffset < 0) {
138:                    throw new IllegalArgumentException("startOffset="
139:                            + startOffset + " < 0"); // NOI18N
140:                }
141:                if (startOffset > endOffset) {
142:                    throw new IllegalArgumentException("startOffset="
143:                            + startOffset // NOI18N
144:                            + " > endOffset=" + endOffset); // NOI18N
145:                }
146:                TokenItem chain = null;
147:                BaseDocument doc = getDocument();
148:                doc.readLock();
149:                try {
150:                    int docLen = doc.getLength();
151:                    endOffset = Math.min(endOffset, docLen);
152:                    if (startOffset < docLen) {
153:                        TokenItemTP tp = new TokenItemTP();
154:                        tp.targetOffset = endOffset;
155:                        tokenizeText(tp, startOffset, endOffset, false);
156:                        chain = tp.getTokenChain();
157:                    }
158:                } finally {
159:                    doc.readUnlock();
160:                }
161:
162:                return chain;
163:            }
164:
165:            /** Called when the document was modified by either the insert or removal.
166:             * @param evt event received with the modification notification. getType()
167:             *   can be used to obtain the type of the event.
168:             */
169:            protected void documentModified(DocumentEvent evt) {
170:                // Invalidate variable maps
171:                if (localVarMaps.size() > 0)
172:                    localVarMaps.clear();
173:                if (globalVarMaps.size() > 0)
174:                    globalVarMaps.clear();
175:            }
176:
177:            /** Get the bracket finder that will search for the matching bracket
178:             * or null if the bracket character doesn't belong to bracket
179:             * characters.
180:             */
181:            protected BracketFinder getMatchingBracketFinder(char bracketChar) {
182:                BracketFinder bf = new BracketFinder(bracketChar);
183:                if (bf.moveCount == 0) { // not valid bracket char
184:                    bf = null;
185:                }
186:
187:                return bf;
188:            }
189:
190:            /** Find matching bracket or more generally block
191:             * that matches with the current position.
192:             * @param offset position of the starting bracket
193:             * @param simple whether the search should skip comment and possibly other areas.
194:             *   This can be useful when the speed is critical, because the simple
195:             *   search is faster.
196:             * @return array of integers containing starting and ending position
197:             *   of the block in the document. Null is returned if there's
198:             *   no matching block.
199:             */
200:            public int[] findMatchingBlock(int offset, boolean simpleSearch)
201:                    throws BadLocationException {
202:                char bracketChar = getDocument().getChars(offset, 1)[0];
203:                int foundPos = -1;
204:
205:                final BracketFinder bf = getMatchingBracketFinder(bracketChar);
206:
207:                if (bf != null) { // valid finder
208:                    if (!simpleSearch) {
209:                        TokenID tokenID = getTokenID(offset);
210:                        TokenID[] bst = getBracketSkipTokens();
211:                        for (int i = bst.length - 1; i >= 0; i--) {
212:                            if (tokenID == bst[i]) {
213:                                simpleSearch = true; // turn to simple search
214:                                break;
215:                            }
216:                        }
217:                    }
218:
219:                    if (simpleSearch) { // don't exclude comments etc.
220:                        if (bf.isForward()) {
221:                            foundPos = getDocument().find(bf, offset, -1);
222:                        } else {
223:                            foundPos = getDocument().find(bf, offset + 1, 0);
224:                        }
225:
226:                    } else { // exclude comments etc. from the search
227:                        TextBatchProcessor tbp = new TextBatchProcessor() {
228:                            public int processTextBatch(BaseDocument doc,
229:                                    int startPos, int endPos, boolean lastBatch) {
230:                                try {
231:                                    int[] blks = getTokenBlocks(startPos,
232:                                            endPos, getBracketSkipTokens());
233:                                    return findOutsideBlocks(bf, startPos,
234:                                            endPos, blks);
235:                                } catch (BadLocationException e) {
236:                                    return -1;
237:                                }
238:                            }
239:                        };
240:
241:                        if (bf.isForward()) {
242:                            foundPos = getDocument().processText(tbp, offset,
243:                                    -1);
244:                        } else {
245:                            foundPos = getDocument().processText(tbp,
246:                                    offset + 1, 0);
247:                        }
248:                    }
249:                }
250:
251:                return (foundPos != -1) ? new int[] { foundPos, foundPos + 1 }
252:                        : null;
253:            }
254:
255:            /** Get the array of token IDs that should be skipped when
256:             * searching for matching bracket. It usually includes comments
257:             * and character and string constants. Returns empty array by default.
258:             */
259:            protected TokenID[] getBracketSkipTokens() {
260:                return EMPTY_TOKEN_ID_ARRAY;
261:            }
262:
263:            /** Gets the token-id of the token at the given position.
264:             * @param offset position at which the token should be returned
265:             * @return token-id of the token at the requested position. If there's no more
266:             *   tokens in the text, the <tt>Syntax.INVALID</tt> is returned.
267:             */
268:            public TokenID getTokenID(int offset) throws BadLocationException {
269:                FirstTokenTP fttp = new FirstTokenTP();
270:                tokenizeText(fttp, offset, getDocument().getLength(), true);
271:                return fttp.getTokenID();
272:            }
273:
274:            /** Is the identifier at the position a function call?
275:             * It first checks whether there is a identifier under
276:             * the cursor and then it searches for the function call
277:             * character - usually '('. Note: Java 1.5 annotations are not
278:             * taken as function calls.
279:             * @param identifierBlock int[2] block delimiting the identifier
280:             * @return int[2] block or null if there's no function call
281:             */
282:            public int[] getFunctionBlock(int[] identifierBlock)
283:                    throws BadLocationException {
284:                if (identifierBlock != null) {
285:                    int nwPos = Utilities.getFirstNonWhiteFwd(getDocument(),
286:                            identifierBlock[1]);
287:                    if ((nwPos >= 0)
288:                            && (getDocument().getChars(nwPos, 1)[0] == '(')) {
289:                        return new int[] { identifierBlock[0], nwPos + 1 };
290:                    }
291:                }
292:                return null;
293:            }
294:
295:            public int[] getFunctionBlock(int offset)
296:                    throws BadLocationException {
297:                return getFunctionBlock(Utilities.getIdentifierBlock(
298:                        getDocument(), offset));
299:            }
300:
301:            public boolean isWhitespaceToken(TokenID tokenID, char[] buffer,
302:                    int offset, int tokenLength) {
303:                return Analyzer.isWhitespace(buffer, offset, tokenLength);
304:            }
305:
306:            public boolean isCommentOrWhitespace(int startPos, int endPos)
307:                    throws BadLocationException {
308:                CommentOrWhitespaceTP tp = new CommentOrWhitespaceTP(
309:                        getCommentTokens());
310:                tokenizeText(tp, startPos, endPos, true);
311:                return !tp.nonEmpty;
312:            }
313:
314:            /** Gets the last non-blank and non-comment character on the given line.
315:             */
316:            public int getRowLastValidChar(int offset)
317:                    throws BadLocationException {
318:                return Utilities.getRowLastNonWhite(getDocument(), offset);
319:            }
320:
321:            /** Does the line contain some valid code besides of possible white space
322:             * and comments?
323:             */
324:            public boolean isRowValid(int offset) throws BadLocationException {
325:                return Utilities.isRowWhite(getDocument(), offset);
326:            }
327:
328:            /** Get the array of token IDs that denote the comments.
329:             * Returns empty array by default.
330:             */
331:            public TokenID[] getCommentTokens() {
332:                return EMPTY_TOKEN_ID_ARRAY;
333:            }
334:
335:            /** Get the blocks consisting of comments in a specified document area.
336:             * @param doc document to work with
337:             * @param startPos starting position of the searched document area
338:             * @param endPos ending position of the searched document area
339:             */
340:            public int[] getCommentBlocks(int startPos, int endPos)
341:                    throws BadLocationException {
342:                return getTokenBlocks(startPos, endPos, getCommentTokens());
343:            }
344:
345:            /** Find the type of the variable. The default behavior is to first
346:             * search for the local variable declaration and then possibly for
347:             * the global declaration and if the declaration position is found
348:             * to get the first word on that position.
349:             * @return it returns Object to enable the custom implementations
350:             *   to return the appropriate instances.
351:             */
352:            public Object findType(String varName, int varPos) {
353:                Object type = null;
354:                Map varMap = getLocalVariableMap(varPos); // first try local vars
355:                if (varMap != null) {
356:                    type = varMap.get(varName);
357:                }
358:
359:                if (type == null) {
360:                    varMap = getGlobalVariableMap(varPos); // try global vars
361:                    if (varMap != null) {
362:                        type = varMap.get(varName);
363:                    }
364:                }
365:
366:                return type;
367:            }
368:
369:            public Map getLocalVariableMap(int offset) {
370:                Integer posI = new Integer(offset);
371:                Map varMap = (Map) localVarMaps.get(posI);
372:                if (varMap == null) {
373:                    varMap = buildLocalVariableMap(offset);
374:                    localVarMaps.put(posI, varMap);
375:                }
376:                return varMap;
377:            }
378:
379:            protected Map buildLocalVariableMap(int offset) {
380:                int methodStartPos = getMethodStartPosition(offset);
381:                if (methodStartPos >= 0 && methodStartPos < offset) {
382:                    VariableMapTokenProcessor vmtp = createVariableMapTokenProcessor(
383:                            methodStartPos, offset);
384:                    try {
385:                        tokenizeText(vmtp, methodStartPos, offset, true);
386:                        return vmtp.getVariableMap();
387:                    } catch (BadLocationException e) {
388:                        // will default null
389:                    }
390:                }
391:                return null;
392:            }
393:
394:            public Map getGlobalVariableMap(int offset) {
395:                Integer posI = new Integer(offset);
396:                Map varMap = (Map) globalVarMaps.get(posI);
397:                if (varMap == null) {
398:                    varMap = buildGlobalVariableMap(offset);
399:                    globalVarMaps.put(posI, varMap);
400:                }
401:                return varMap;
402:            }
403:
404:            protected Map buildGlobalVariableMap(int offset) {
405:                int docLen = getDocument().getLength();
406:                VariableMapTokenProcessor vmtp = createVariableMapTokenProcessor(
407:                        0, docLen);
408:                if (vmtp != null) {
409:                    try {
410:                        tokenizeText(vmtp, 0, docLen, true);
411:                        return vmtp.getVariableMap();
412:                    } catch (BadLocationException e) {
413:                        // will default null
414:                    }
415:                }
416:                return null;
417:            }
418:
419:            /** Get the start position of the method or the area
420:             * where the declaration can start.
421:             */
422:            protected int getMethodStartPosition(int offset) {
423:                return 0; // return begining of the document by default
424:            }
425:
426:            /** Find either the local or global declaration position. First
427:             * try the local declaration and if it doesn't succeed, then
428:             * try the global declaration.
429:             */
430:            public int findDeclarationPosition(String varName, int varPos) {
431:                int offset = findLocalDeclarationPosition(varName, varPos);
432:                if (offset < 0) {
433:                    offset = findGlobalDeclarationPosition(varName, varPos);
434:                }
435:                return offset;
436:            }
437:
438:            public int findLocalDeclarationPosition(String varName, int varPos) {
439:                int methodStartPos = getMethodStartPosition(varPos);
440:                if (methodStartPos >= 0 && methodStartPos < varPos) {
441:                    return findDeclarationPositionImpl(varName, methodStartPos,
442:                            varPos);
443:                }
444:                return -1;
445:            }
446:
447:            /** Get the position of the global declaration of a given variable.
448:             * By default it's implemented to use the same token processor as for the local
449:             * variables but the whole file is searched.
450:             */
451:            public int findGlobalDeclarationPosition(String varName, int varPos) {
452:                return findDeclarationPositionImpl(varName, 0, getDocument()
453:                        .getLength());
454:            }
455:
456:            private int findDeclarationPositionImpl(String varName,
457:                    int startPos, int endPos) {
458:                DeclarationTokenProcessor dtp = createDeclarationTokenProcessor(
459:                        varName, startPos, endPos);
460:                if (dtp != null) {
461:                    try {
462:                        tokenizeText(dtp, startPos, endPos, true);
463:                        return dtp.getDeclarationPosition();
464:                    } catch (BadLocationException e) {
465:                        // will default to -1
466:                    }
467:                }
468:                return -1;
469:            }
470:
471:            protected DeclarationTokenProcessor createDeclarationTokenProcessor(
472:                    String varName, int startPos, int endPos) {
473:                return null;
474:            }
475:
476:            protected VariableMapTokenProcessor createVariableMapTokenProcessor(
477:                    int startPos, int endPos) {
478:                return null;
479:            }
480:
481:            /** Check and possibly popup, hide or refresh the completion */
482:            public int checkCompletion(JTextComponent target, String typedText,
483:                    boolean visible) {
484:                return visible ? COMPLETION_HIDE : COMPLETION_CANCEL;
485:            }
486:
487:            /** Token processor extended to get declaration position
488:             * of the given variable.
489:             */
490:            public interface DeclarationTokenProcessor extends TokenProcessor {
491:
492:                /** Get the declaration position. */
493:                public int getDeclarationPosition();
494:
495:            }
496:
497:            public interface VariableMapTokenProcessor extends TokenProcessor {
498:
499:                /** Get the map that contains the pairs [variable-name, variable-type]. */
500:                public Map getVariableMap();
501:
502:            }
503:
504:            /** Finder for the matching bracket. It gets the original bracket char
505:             * and searches for the appropriate matching bracket character.
506:             */
507:            public class BracketFinder extends FinderFactory.GenericFinder {
508:
509:                /** Original bracket char */
510:                protected char bracketChar;
511:
512:                /** Matching bracket char */
513:                protected char matchChar;
514:
515:                /** Depth of original brackets */
516:                private int depth;
517:
518:                /** Will it be a forward finder +1 or backward finder -1 or 0 when
519:                 * the given character is not bracket character.
520:                 */
521:                protected int moveCount;
522:
523:                /**
524:                 * @param bracketChar bracket char
525:                 */
526:                public BracketFinder(char bracketChar) {
527:                    this .bracketChar = bracketChar;
528:
529:                    updateStatus();
530:
531:                    forward = (moveCount > 0);
532:                }
533:
534:                /** Check whether the bracketChar really contains
535:                 * the bracket character. If so assign the matchChar
536:                 * and moveCount variables.
537:                 */
538:                protected boolean updateStatus() {
539:                    boolean valid = true;
540:                    switch (bracketChar) {
541:                    case '(':
542:                        matchChar = ')';
543:                        moveCount = +1;
544:                        break;
545:                    case ')':
546:                        matchChar = '(';
547:                        moveCount = -1;
548:                        break;
549:                    case '{':
550:                        matchChar = '}';
551:                        moveCount = +1;
552:                        break;
553:                    case '}':
554:                        matchChar = '{';
555:                        moveCount = -1;
556:                        break;
557:                    case '[':
558:                        matchChar = ']';
559:                        moveCount = +1;
560:                        break;
561:                    case ']':
562:                        matchChar = '[';
563:                        moveCount = -1;
564:                        break;
565:                    case '<':
566:                        matchChar = '>';
567:                        moveCount = +1;
568:                        break;
569:                    case '>':
570:                        matchChar = '<';
571:                        moveCount = -1;
572:                        break;
573:                    default:
574:                        valid = false;
575:                    }
576:                    return valid;
577:                }
578:
579:                protected int scan(char ch, boolean lastChar) {
580:                    if (ch == bracketChar) {
581:                        depth++;
582:                    } else if (ch == matchChar) {
583:                        if (--depth == 0) {
584:                            found = true;
585:                            return 0;
586:                        }
587:                    }
588:                    return moveCount;
589:                }
590:
591:            }
592:
593:            /** Create token-items */
594:            final class TokenItemTP implements  TokenProcessor {
595:
596:                private Item firstItem;
597:
598:                private Item lastItem;
599:
600:                private int fwdBatchLineCnt;
601:                private int bwdBatchLineCnt;
602:
603:                private char[] buffer;
604:
605:                private int bufferStartPos;
606:
607:                /** Target position corresponding to the begining of the token
608:                 * that is already chained if searching for backward tokens,
609:                 * or, the last token that should be scanned if searching
610:                 * in forward direction.
611:                 */
612:                int targetOffset;
613:
614:                TokenItemTP() {
615:                    fwdBatchLineCnt = bwdBatchLineCnt = ((Integer) getDocument()
616:                            .getProperty(SettingsNames.LINE_BATCH_SIZE))
617:                            .intValue();
618:                }
619:
620:                public TokenItem getTokenChain() {
621:                    return firstItem;
622:                }
623:
624:                public boolean token(TokenID tokenID,
625:                        TokenContextPath tokenContextPath,
626:                        int tokenBufferOffset, int tokenLength) {
627:                    if (bufferStartPos + tokenBufferOffset >= targetOffset) { // stop scanning
628:                        return false;
629:                    }
630:
631:                    lastItem = new Item(tokenID, tokenContextPath,
632:                            bufferStartPos + tokenBufferOffset, new String(
633:                                    buffer, tokenBufferOffset, tokenLength),
634:                            lastItem);
635:
636:                    if (firstItem == null) { // not yet assigned
637:                        firstItem = lastItem;
638:                    }
639:
640:                    return true;
641:                }
642:
643:                public int eot(int offset) {
644:                    return ((Integer) getDocument().getProperty(
645:                            SettingsNames.MARK_DISTANCE)).intValue();
646:                }
647:
648:                public void nextBuffer(char[] buffer, int offset, int len,
649:                        int startPos, int preScan, boolean lastBuffer) {
650:                    this .buffer = buffer;
651:                    bufferStartPos = startPos - offset;
652:                }
653:
654:                Item getNextChunk(Item i) {
655:                    BaseDocument doc = getDocument();
656:                    int itemEndPos = i.getOffset() + i.getImage().length();
657:                    int docLen = doc.getLength();
658:                    if (itemEndPos == docLen) {
659:                        return null;
660:                    }
661:
662:                    int endPos;
663:                    try {
664:                        endPos = Utilities.getRowStart(doc, itemEndPos,
665:                                fwdBatchLineCnt);
666:                    } catch (BadLocationException e) {
667:                        return null;
668:                    }
669:
670:                    if (endPos == -1) { // past end of doc
671:                        endPos = docLen;
672:                    }
673:                    fwdBatchLineCnt *= 2; // larger batch in next call
674:
675:                    Item nextChunkHead = null;
676:                    Item fit = firstItem;
677:                    Item lit = lastItem;
678:                    try {
679:                        // Simulate initial conditions
680:                        firstItem = null;
681:                        lastItem = null;
682:                        targetOffset = endPos;
683:
684:                        tokenizeText(this , itemEndPos, endPos, false);
685:                        nextChunkHead = firstItem;
686:
687:                    } catch (BadLocationException e) {
688:                    } finally {
689:                        // Link previous last with the current first
690:                        if (firstItem != null) {
691:                            lit.next = firstItem;
692:                            firstItem.previous = lit;
693:                        }
694:
695:                        firstItem = fit;
696:                        if (lastItem == null) { // restore in case of no token or crash
697:                            lastItem = lit;
698:                        }
699:                    }
700:
701:                    return nextChunkHead;
702:                }
703:
704:                Item getPreviousChunk(Item i) {
705:                    BaseDocument doc = getDocument();
706:                    int itemStartPos = i.getOffset();
707:                    if (itemStartPos == 0) {
708:                        return null;
709:                    }
710:
711:                    int startPos;
712:                    try {
713:                        startPos = Utilities.getRowStart(doc, itemStartPos,
714:                                -bwdBatchLineCnt);
715:                    } catch (BadLocationException e) {
716:                        return null;
717:                    }
718:
719:                    if (startPos == -1) { // before begining of doc
720:                        startPos = 0;
721:                    }
722:                    bwdBatchLineCnt *= 2;
723:
724:                    Item previousChunkLast = null;
725:                    Item fit = firstItem;
726:                    Item lit = lastItem;
727:                    try {
728:                        // Simulate initial conditions
729:                        firstItem = null;
730:                        lastItem = null;
731:                        targetOffset = itemStartPos;
732:
733:                        tokenizeText(this , startPos, itemStartPos, false);
734:                        previousChunkLast = lastItem;
735:
736:                    } catch (BadLocationException e) {
737:                    } finally {
738:                        // Link previous last
739:                        if (lastItem != null) {
740:                            fit.previous = lastItem;
741:                            lastItem.next = fit;
742:                        }
743:
744:                        lastItem = lit;
745:                        if (firstItem == null) { // restore in case of no token or crash
746:                            firstItem = fit;
747:                        }
748:                    }
749:
750:                    return previousChunkLast;
751:                }
752:
753:                final class Item extends TokenItem.AbstractItem {
754:
755:                    Item previous;
756:
757:                    TokenItem next;
758:
759:                    Item(TokenID tokenID, TokenContextPath tokenContextPath,
760:                            int offset, String image, Item previous) {
761:                        super (tokenID, tokenContextPath, offset, image);
762:                        if (previous != null) {
763:                            this .previous = previous;
764:                            previous.next = this ;
765:                        }
766:                    }
767:
768:                    public TokenItem getNext() {
769:                        if (next == null) {
770:                            next = getNextChunk(this );
771:                        }
772:                        return next;
773:                    }
774:
775:                    public TokenItem getPrevious() {
776:                        if (previous == null) {
777:                            previous = getPreviousChunk(this );
778:                        }
779:                        return previous;
780:                    }
781:
782:                }
783:
784:            }
785:
786:            /** Token processor that matches either the comments or whitespace */
787:            class CommentOrWhitespaceTP implements  TokenProcessor {
788:
789:                private char[] buffer;
790:
791:                private TokenID[] commentTokens;
792:
793:                boolean nonEmpty;
794:
795:                CommentOrWhitespaceTP(TokenID[] commentTokens) {
796:                    this .commentTokens = commentTokens;
797:                }
798:
799:                public boolean token(TokenID tokenID,
800:                        TokenContextPath tokenContextPath, int offset,
801:                        int tokenLength) {
802:                    for (int i = 0; i < commentTokens.length; i++) {
803:                        if (tokenID == commentTokens[i]) {
804:                            return true; // comment token found
805:                        }
806:                    }
807:                    boolean nonWS = isWhitespaceToken(tokenID, buffer, offset,
808:                            tokenLength);
809:                    if (nonWS) {
810:                        nonEmpty = true;
811:                    }
812:                    return nonWS;
813:                }
814:
815:                public int eot(int offset) {
816:                    return 0;
817:                }
818:
819:                public void nextBuffer(char[] buffer, int offset, int len,
820:                        int startPos, int preScan, boolean lastBuffer) {
821:                    this .buffer = buffer;
822:                }
823:
824:            }
825:
826:            static class FirstTokenTP implements  TokenProcessor {
827:
828:                private TokenID tokenID;
829:
830:                public TokenID getTokenID() {
831:                    return tokenID;
832:                }
833:
834:                public boolean token(TokenID tokenID,
835:                        TokenContextPath tokenContextPath, int offset,
836:                        int tokenLen) {
837:                    this .tokenID = tokenID;
838:                    return false; // no more tokens
839:                }
840:
841:                public int eot(int offset) {
842:                    return 0;
843:                }
844:
845:                public void nextBuffer(char[] buffer, int offset, int len,
846:                        int startPos, int preScan, boolean lastBuffer) {
847:                }
848:
849:            }
850:
851:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.