Source Code Cross Referenced for FindReplaceMachine.java in  » IDE » DrJava » edu » rice » cs » drjava » model » 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 » DrJava » edu.rice.cs.drjava.model 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*BEGIN_COPYRIGHT_BLOCK
002:         *
003:         * Copyright (c) 2001-2007, JavaPLT group at Rice University (javaplt@rice.edu)
004:         * All rights reserved.
005:         * 
006:         * Redistribution and use in source and binary forms, with or without
007:         * modification, are permitted provided that the following conditions are met:
008:         *    * Redistributions of source code must retain the above copyright
009:         *      notice, this list of conditions and the following disclaimer.
010:         *    * Redistributions in binary form must reproduce the above copyright
011:         *      notice, this list of conditions and the following disclaimer in the
012:         *      documentation and/or other materials provided with the distribution.
013:         *    * Neither the names of DrJava, the JavaPLT group, Rice University, nor the
014:         *      names of its contributors may be used to endorse or promote products
015:         *      derived from this software without specific prior written permission.
016:         * 
017:         * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
018:         * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
019:         * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
020:         * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
021:         * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
022:         * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
023:         * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
024:         * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
025:         * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
026:         * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
027:         * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
028:         *
029:         * This software is Open Source Initiative approved Open Source Software.
030:         * Open Source Initative Approved is a trademark of the Open Source Initiative.
031:         * 
032:         * This file is part of DrJava.  Download the current version of this project
033:         * from http://www.drjava.org/ or http://sourceforge.net/projects/drjava/
034:         * 
035:         * END_COPYRIGHT_BLOCK*/
036:
037:        package edu.rice.cs.drjava.model;
038:
039:        import edu.rice.cs.drjava.model.definitions.reducedmodel.ReducedModelStates;
040:
041:        import edu.rice.cs.util.UnexpectedException;
042:        import edu.rice.cs.util.swing.DocumentIterator;
043:        import edu.rice.cs.util.swing.Utilities;
044:        import edu.rice.cs.util.text.AbstractDocumentInterface;
045:        import edu.rice.cs.util.Lambda;
046:        import edu.rice.cs.util.Log;
047:        import edu.rice.cs.util.StringOps;
048:
049:        import java.awt.EventQueue;
050:
051:        import javax.swing.text.BadLocationException;
052:        import javax.swing.text.Position;
053:
054:        /** Implementation of logic of find/replace over a document.
055:         *  @version $Id: FindReplaceMachine.java 4255 2007-08-28 19:17:37Z mgricken $
056:         */
057:        public class FindReplaceMachine {
058:
059:            // TODO: is _start still used in any way that matters?
060:
061:            static private Log _log = new Log("FindReplace.txt", false);
062:
063:            /* Visible machine state; manipulated directly or indirectly by FindReplacePanel. */
064:            private OpenDefinitionsDocument _doc; // Current search document 
065:            private OpenDefinitionsDocument _firstDoc; // First document where searching started (when searching all documents)
066:            //  private Position _current;                 // Position of the cursor in _doc when machine is stopped
067:            private int _current; // Position of the cursor in _doc when machine is stopped
068:            //  private Position _start;                   // Position in _doc from which searching started or will start.
069:            private String _findWord; // Word to find. */
070:            private String _replaceWord; // Word to replace _findword.
071:            private boolean _matchCase;
072:            private boolean _matchWholeWord;
073:            private boolean _searchAllDocuments; // Whether to search all documents (or just the current document)
074:            private boolean _isForward; // Whether search direction is forward (false means backward)
075:            private boolean _ignoreCommentsAndStrings; // Whether to ignore matches in comments and strings
076:            private String _lastFindWord; // Last word found; set to null by FindReplacePanel if caret is updated
077:            private boolean _skipText; // Whether to skip over the current match if direction is reversed
078:            private DocumentIterator _docIterator; // An iterator of open documents; _doc is current
079:            private SingleDisplayModel _model;
080:
081:            /** Standard Constructor.
082:             *  Creates new machine to perform find/replace operations on a particular document starting from a given position.
083:             *  @param docIterator an object that allows navigation through open Swing documents (it is DefaultGlobalModel)
084:             *  @exception BadLocationException
085:             */
086:            public FindReplaceMachine(SingleDisplayModel model,
087:                    DocumentIterator docIterator) {
088:                _skipText = false;
089:                //    _checkAllDocsWrapped = false;
090:                //    _allDocsWrapped = false;
091:                _model = model;
092:                _docIterator = docIterator;
093:                _current = -1;
094:                setFindAnyOccurrence();
095:                setFindWord("");
096:                setReplaceWord("");
097:                setSearchBackwards(false);
098:                setMatchCase(true);
099:                setSearchAllDocuments(false);
100:                setIgnoreCommentsAndStrings(false);
101:            }
102:
103:            public void cleanUp() {
104:                _docIterator = null;
105:                setFindWord("");
106:                _doc = null;
107:            }
108:
109:            /** Called when the current position is updated in the document implying _skipText should not be set
110:             *  if the user toggles _searchBackwards
111:             */
112:            public void positionChanged() {
113:                _lastFindWord = null;
114:                _skipText = false;
115:            }
116:
117:            public void setLastFindWord() {
118:                _lastFindWord = _findWord;
119:            }
120:
121:            public boolean getSearchBackwards() {
122:                return !_isForward;
123:            }
124:
125:            public void setSearchBackwards(boolean searchBackwards) {
126:                if (_isForward == searchBackwards) {
127:                    // If we switch from searching forward to searching backwards or viceversa, isOnMatch is true, and _findword is the
128:                    // same as the _lastFindWord, we know the user just found _findWord, so skip over this match.
129:                    if (onMatch() && _findWord.equals(_lastFindWord))
130:                        _skipText = true;
131:                    else
132:                        _skipText = false;
133:                }
134:                _isForward = !searchBackwards;
135:            }
136:
137:            public void setMatchCase(boolean matchCase) {
138:                _matchCase = matchCase;
139:            }
140:
141:            public void setMatchWholeWord() {
142:                _matchWholeWord = true;
143:            }
144:
145:            public void setFindAnyOccurrence() {
146:                _matchWholeWord = false;
147:            }
148:
149:            public void setSearchAllDocuments(boolean searchAllDocuments) {
150:                _searchAllDocuments = searchAllDocuments;
151:            }
152:
153:            public void setIgnoreCommentsAndStrings(
154:                    boolean ignoreCommentsAndStrings) {
155:                _ignoreCommentsAndStrings = ignoreCommentsAndStrings;
156:            }
157:
158:            public void setDocument(OpenDefinitionsDocument doc) {
159:                _doc = doc;
160:            }
161:
162:            public void setFirstDoc(OpenDefinitionsDocument firstDoc) {
163:                _firstDoc = firstDoc;
164:            }
165:
166:            public void setPosition(int pos) {
167:                //    System.err.println("Setting position " + pos + " in doc [" + _doc.getText() + "]");
168:                //    assert (pos >= 0) && (pos <= _doc.getLength());
169:                //try { //_current = _doc.createPosition(pos);
170:                _current = pos;
171:                //}
172:                //catch (BadLocationException ble) { throw new UnexpectedException(ble); }
173:            }
174:
175:            /** Gets the character offset to which this machine is currently pointing. */
176:            public int getCurrentOffset() { //return _current.getOffset(); 
177:                return _current;
178:            }
179:
180:            public String getFindWord() {
181:                return _findWord;
182:            }
183:
184:            public String getReplaceWord() {
185:                return _replaceWord;
186:            }
187:
188:            public boolean getSearchAllDocuments() {
189:                return _searchAllDocuments;
190:            }
191:
192:            public OpenDefinitionsDocument getDocument() {
193:                return _doc;
194:            }
195:
196:            public OpenDefinitionsDocument getFirstDoc() {
197:                return _firstDoc;
198:            }
199:
200:            /** Change the word being sought.
201:             *  @param word the new word to seek
202:             */
203:            public void setFindWord(String word) {
204:                _findWord = StringOps.replace(word, StringOps.EOL, "\n");
205:            }
206:
207:            /** Change the replacing word.
208:             *  @param word the new replacing word
209:             */
210:            public void setReplaceWord(String word) {
211:                _replaceWord = StringOps.replace(word, StringOps.EOL, "\n");
212:            }
213:
214:            /** Determine if the machine is on an instance of the find word.  Only executes in event thread except for
215:             * initialization.
216:             * @return true if the current position is right after an instance of the find word.
217:             */
218:            public boolean onMatch() {
219:
220:                //    assert EventQueue.isDispatchThread();
221:
222:                String findWord = _findWord;
223:                int wordLen, off;
224:
225:                if (_current == -1)
226:                    return false;
227:
228:                wordLen = findWord.length();
229:                if (_isForward)
230:                    off = getCurrentOffset() - wordLen;
231:                else
232:                    off = getCurrentOffset();
233:
234:                if (off < 0)
235:                    return false;
236:
237:                String matchSpace;
238:                try {
239:                    if (off + wordLen > _doc.getLength())
240:                        return false;
241:                    matchSpace = _doc.getText(off, wordLen);
242:                } catch (BadLocationException e) {
243:                    throw new UnexpectedException(e);
244:                }
245:
246:                if (!_matchCase) {
247:                    matchSpace = matchSpace.toLowerCase();
248:                    findWord = findWord.toLowerCase();
249:                }
250:                return matchSpace.equals(findWord);
251:            }
252:
253:            /** If we're on a match for the find word, replace it with the replace word.  Only executes in event thread. */
254:            public boolean replaceCurrent() {
255:
256:                assert EventQueue.isDispatchThread();
257:
258:                if (!onMatch())
259:                    return false;
260:                _doc.acquireWriteLock();
261:                try {
262:                    //      boolean atStart = false;
263:                    int offset = getCurrentOffset();
264:                    if (_isForward)
265:                        offset -= _findWord.length(); // position is now on left edge of match
266:                        //      assert _findWord.equals(_doc.getText(offset, _findWord.length()));
267:
268:                    //      Utilities.show("ReplaceCurrent called. _doc = " + _doc.getText() + " offset = " + offset + " _findWord = " + _findWord);
269:
270:                    _doc.remove(offset, _findWord.length());
271:
272:                    //      if (position == 0) atStart = true;
273:                    _doc.insertString(offset, _replaceWord, null);
274:
275:                    // update _current Position
276:                    if (_isForward)
277:                        setPosition(offset + _replaceWord.length());
278:                    else
279:                        setPosition(offset);
280:
281:                    return true;
282:                } catch (BadLocationException e) {
283:                    throw new UnexpectedException(e);
284:                } finally {
285:                    _doc.releaseWriteLock();
286:                }
287:            }
288:
289:            /** Replaces all occurences of the find word with the replace word in the current document of in all documents
290:             *  depending the value of the machine register _searchAllDocuments.
291:             *  @return the number of replacements
292:             */
293:            public int replaceAll() {
294:                return replaceAll(_searchAllDocuments);
295:            }
296:
297:            /** Replaces all occurences of the find word with the replace word in the current document of in all documents
298:             *  depending the value of the flag searchAll. 
299:             *  @return the number of replacements
300:             */
301:            private int replaceAll(boolean searchAll) {
302:                if (searchAll) {
303:                    OpenDefinitionsDocument startDoc = _doc;
304:                    int count = 0; // the number of replacements done so farr
305:                    int n = _docIterator.getDocumentCount();
306:                    for (int i = 0; i < n; i++) {
307:                        // replace all in the rest of the documents
308:                        count += _replaceAllInCurrentDoc();
309:                        _doc = _docIterator.getNextDocument(_doc);
310:                    }
311:
312:                    // update display (adding "*") in navigatgorPane
313:                    _model.getDocumentNavigator().repaint();
314:
315:                    return count;
316:                } else
317:                    return _replaceAllInCurrentDoc();
318:            }
319:
320:            /** Replaces all occurences of _findWord with _replaceWord in _doc. Never searches in other documents.  Starts at
321:             *  the beginning or the end of the document (depending on find direction).  This convention ensures that matches 
322:             *  created by string replacement will not be replaced as in the following example:<p>
323:             *    findString:    "hello"<br>
324:             *    replaceString: "e"<br>
325:             *    document text: "hhellollo"<p>
326:             *  Depending on the cursor position, clicking replace all could either make the document text read "hello" 
327:             *  (which is correct) or "e".  This is because of the behavior of findNext(), and it would be incorrect
328:             *  to change that behavior.  Only executes in event thread.
329:             *  @return the number of replacements
330:             */
331:            private int _replaceAllInCurrentDoc() {
332:
333:                assert EventQueue.isDispatchThread();
334:
335:                if (_isForward)
336:                    setPosition(0);
337:                else
338:                    setPosition(_doc.getLength());
339:
340:                int count = 0;
341:                FindResult fr = findNext(false); // find next match in current doc   
342:                //      Utilities.show(fr + " returned by call on findNext()");
343:
344:                while (!fr.getWrapped()) {
345:                    replaceCurrent(); // sets writeLock so that other threads do not see inconsistent state
346:                    count++;
347:                    //        Utilities.show("Found " + count + " occurrences. Calling findNext() inside loop");
348:                    fr = findNext(false); // find next match in current doc
349:                    //        Utilities.show("Call on findNext() returned " + fr.toString() + "in doc '" + _doc.getText() + "'");
350:                }
351:                return count;
352:            }
353:
354:            /** Processes all occurences of the find word with the replace word in the current document or in all documents
355:             *  depending the value of the machine register _searchAllDocuments.
356:             *  @param findAction action to perform on the occurrences; input is the FindResult, output is ignored
357:             *  @return the number of processed occurrences
358:             */
359:            public int processAll(Lambda<Void, FindResult> findAction) {
360:                return processAll(findAction, _searchAllDocuments);
361:            }
362:
363:            /** Processes all occurences of the find word with the replace word in the current document of in all documents
364:             *  depending the value of the flag searchAll.  Only executes in event thread.
365:             *  @param findAction action to perform on the occurrences; input is the FindResult, output is ignored
366:             *  @return the number of replacements
367:             */
368:            private int processAll(Lambda<Void, FindResult> findAction,
369:                    boolean searchAll) {
370:
371:                assert EventQueue.isDispatchThread();
372:
373:                if (searchAll) {
374:                    OpenDefinitionsDocument startDoc = _doc;
375:                    int count = 0; // the number of replacements done so farr
376:                    int n = _docIterator.getDocumentCount();
377:                    for (int i = 0; i < n; i++) {
378:                        // process all in the rest of the documents
379:                        count += _processAllInCurrentDoc(findAction);
380:                        _doc = _docIterator.getNextDocument(_doc);
381:                    }
382:
383:                    // update display (perhaps adding "*") in navigatgorPane
384:                    _model.getDocumentNavigator().repaint();
385:
386:                    return count;
387:                } else
388:                    return _processAllInCurrentDoc(findAction);
389:            }
390:
391:            /** Processes all occurences of _findWord in _doc. Never processes other documents.  Starts at
392:             *  the beginning or the end of the document (depending on find direction).  This convention ensures that matches 
393:             *  created by string replacement will not be replaced as in the following example:<p>
394:             *    findString:    "hello"<br>
395:             *    replaceString: "e"<br>
396:             *    document text: "hhellollo"<p>
397:             *  Only executes in event thread.
398:             *  @param findAction action to perform on the occurrences; input is the FindResult, output is ignored
399:             *  @return the number of replacements
400:             */
401:            private int _processAllInCurrentDoc(
402:                    Lambda<Void, FindResult> findAction) {
403:
404:                if (_isForward)
405:                    setPosition(0);
406:                else
407:                    setPosition(_doc.getLength());
408:
409:                int count = 0;
410:                FindResult fr = findNext(false); // find next match in current doc   
411:
412:                while (!fr.getWrapped()) {
413:                    findAction.apply(fr);
414:                    count++;
415:                    fr = findNext(false); // find next match in current doc
416:                }
417:                return count;
418:            }
419:
420:            public FindResult findNext() {
421:                return findNext(_searchAllDocuments);
422:            }
423:
424:            /** Finds the next occurrence of the find word and returns an offset at the end of that occurrence or -1 if the word
425:             *  was not found.  Selectors should select backwards the length of the find word from the find offset.  This 
426:             *  position is stored in the current offset of the machine, and that is why it is after: in subsequent searches, the
427:             *  same instance won't be found twice.  In a backward search, the position returned is at the beginning of the word.  
428:             *  Also returns a flag indicating whether the end of the document was reached and wrapped around. This is done
429:             *  using the FindResult class which contains the matching document, an integer offset and two flag indicated whether
430:             *  the search wrapped (within _doc and across all documents).  Only executes in the event thread.
431:             *  @param searchAll whether to search all documents (or just _doc)
432:             *  @return a FindResult object containing foundOffset and a flag indicating wrapping to the beginning during a search
433:             */
434:            private FindResult findNext(boolean searchAll) {
435:
436:                assert EventQueue.isDispatchThread();
437:
438:                // Find next match, if any, in _doc. 
439:                FindResult fr;
440:                int start;
441:                int len;
442:
443:                // If the user just found a match and toggled the "Search Backwards" option, we should skip the matched text.
444:                if (_skipText) { // adjust position (offset)
445:                //      System.err.println("Skip text is true!  Last find word = " + _lastFindWord);
446:                    int wordLen = _lastFindWord.length();
447:                    if (_isForward)
448:                        setPosition(getCurrentOffset() + wordLen);
449:                    else
450:                        setPosition(getCurrentOffset() - wordLen);
451:                    positionChanged();
452:                }
453:
454:                //    System.err.println("findNext(" + searchAll + ") called with _doc = [" + _doc.getText() + "] and offset = " + _current.getOffset());
455:
456:                int offset = getCurrentOffset();
457:                //    System.err.println("findNext(" + searchAll + ") called; initial offset is " + offset);
458:                //    System.err.println("_doc = [" + _doc.getText() + "], _doc.getLength() = " + _doc.getLength());
459:                if (_isForward) {
460:                    start = offset;
461:                    len = _doc.getLength() - offset;
462:                } else {
463:                    start = 0;
464:                    len = offset;
465:                }
466:                fr = _findNextInDoc(_doc, start, len, searchAll);
467:                if ((fr.getFoundOffset() >= 0) || !searchAll)
468:                    return fr; // match found in _doc or search is local
469:
470:                // find match in other docs
471:                return _findNextInOtherDocs(_doc, start, len);
472:            }
473:
474:            /** Finds next match in specified doc only.  If searching forward, len must be doc.getLength().  If searching backward,
475:             *  start must be 0.  If searchAll, suppress executing in-document wrapped search, because it must be deferred.  Assumes
476:             *  acquireReadLock is already held.  Note than this method does a wrapped search if specified search fails.
477:             */
478:            private FindResult _findNextInDoc(OpenDefinitionsDocument doc,
479:                    int start, int len, boolean searchAll) {
480:                // search from current position to "end" of document ("end" is start if searching backward)
481:                _log.log("_findNextInDoc([" + doc.getText() + "], " + start
482:                        + ", " + len + ", " + searchAll + ")");
483:                FindResult fr = _findNextInDocSegment(doc, start, len);
484:                if (fr.getFoundOffset() >= 0 || searchAll)
485:                    return fr;
486:
487:                return _findWrapped(doc, start, len, false); // last arg is false because search has not wrapped through all docs
488:            }
489:
490:            /** Helper method for findNext that looks for a match after searching has wrapped off the "end" (start if searching
491:             *  backward) of the document. Assumes acquireReadLock is already held!  
492:             *  INVARIANT (! _isForward => start = 0) && (_isForward => start + len = doc.getLength()).
493:             *  @param doc  the document in which search wrapped
494:             *  @param start location of preceding text segment where search FAILED.  
495:             *  @param len  length of text segment previously searched
496:             *  @param allWrapped  whether this wrapped search is being performed after an all document search has wrapped
497:             *  @return the offset where the instance was found. Returns -1 if no instance was found between start and end
498:             */
499:            private FindResult _findWrapped(OpenDefinitionsDocument doc,
500:                    int start, int len, boolean allWrapped) {
501:
502:                assert (_isForward && start + len == doc.getLength())
503:                        || (!_isForward && start == 0);
504:
505:                _log.log("_findWrapped(" + doc + ", " + start + ", " + len
506:                        + ", " + allWrapped + ")  docLength = "
507:                        + doc.getLength() + ", _isForward = " + _isForward);
508:
509:                if (doc.getLength() == 0)
510:                    return new FindResult(doc, -1, true, allWrapped);
511:
512:                final int newLen, newStart;
513:                if (_isForward) {
514:                    newStart = 0;
515:                    newLen = start;
516:                } else {
517:                    newStart = len;
518:                    newLen = doc.getLength() - len;
519:                }
520:                _log.log("Calling _findNextInDocSegment(" + doc.getText()
521:                        + ", newStart = " + newStart + ", newLen = " + newLen
522:                        + ", allWrapped = " + allWrapped
523:                        + ") and _isForward = " + _isForward);
524:                return _findNextInDocSegment(doc, newStart, newLen, true,
525:                        allWrapped);
526:            }
527:
528:            /** Find first valid match withing specified segment of doc. */
529:            private FindResult _findNextInDocSegment(
530:                    OpenDefinitionsDocument doc, int start, int len) {
531:                return _findNextInDocSegment(doc, start, len, false, false);
532:            }
533:
534:            /** Main helper method for findNext... that searches for _findWord inside the specified document segment.  Assumes
535:             *  acquireReadLock is already held!
536:             *  @param doc document to be searched
537:             *  @param start the location (offset) of the text segment to be searched 
538:             *  @param len the length of the text segment to be searched
539:             *  @param whether this search should span all documents
540:             *  @param wrapped whether this search is after wrapping around the document
541:             *  @param allWrapped whether this seach is after wrapping around all documents
542:             *  @return a FindResult object with foundOffset and a flag indicating wrapping to the beginning during a search. The
543:             *  foundOffset returned insided the FindResult is -1 if no instance was found.
544:             */
545:            private FindResult _findNextInDocSegment(
546:                    final OpenDefinitionsDocument doc, final int start,
547:                    final int origLen, final boolean wrapped,
548:                    final boolean allWrapped) {
549:                //    Utilities.show("called _findNextInDocSegment(" + doc.getText() + ",\n" + start + ", " + len + ", " + wrapped + " ...)");
550:
551:                assert start > -1;
552:
553:                final int docLen = doc.getLength();
554:                ; // The length of the segment to be searched
555:
556:                final int len = (origLen < 0) ? docLen - start : origLen; // set len for end of doc if origLen < 0
557:
558:                if (len == 0 || docLen == 0)
559:                    return new FindResult(doc, -1, wrapped, allWrapped);
560:
561:                String text; // The text segment to be searched
562:                final String findWord; // copy of word being searched (so it can converted to lower case if necessary
563:                final int wordLen = _findWord.length(); // length of search key (word being searched fo  
564:
565:                try {
566:
567:                    //      if (wrapped && allWrapped) Utilities.show(start +", " + len + ", " + docLen + ", doc = '" + doc.getText() + "'");
568:                    //doc.acquireReadLock(); 
569:                    text = doc.getText(start, len);
570:                    //finally { doc.releaseReadLock(); }
571:
572:                    if (!_matchCase) {
573:                        text = text.toLowerCase();
574:                        findWord = _findWord.toLowerCase(); // does not affect wordLen
575:                    } else
576:                        findWord = _findWord;
577:                    //       if (wrapped && allWrapped) Utilities.show("Executing loop with findWord = " + findWord + "; text = " + text + "; len = " + len);     
578:
579:                    // loop to find first valid (not ignored) occurrence of findWord
580:                    // loop carried variables are rem, foundOffset; 
581:                    // loop invariant variables are _doc, docLen, _isForward, findWord, wordLen, start, len.
582:                    // Invariant:  on forwardsearch, foundOffset + rem == len; on backward search foundOffset == rem.
583:                    // loop exits by returning match (as FindResult) or by falling through with no match.
584:                    // if match is returned, _current has been updated to match location
585:                    int foundOffset = _isForward ? 0 : len;
586:                    int rem = len;
587:                    //      _log.log("Starting search loop; text = '" + text + "' findWord = '" + findWord + "' forward? = " + _isForward + " rem = " + rem + " foundOffset = " + foundOffset);
588:                    while (rem >= wordLen) {
589:
590:                        // Find next match in text
591:                        foundOffset = _isForward ? text.indexOf(findWord,
592:                                foundOffset) : text.lastIndexOf(findWord,
593:                                foundOffset);
594:                        //        _log.log("foundOffset = " + foundOffset);
595:                        if (foundOffset < 0)
596:                            break; // no valid match in this document
597:                        int foundLocation = start + foundOffset;
598:                        int matchLocation;
599:
600:                        if (_isForward) {
601:                            foundOffset += wordLen; // skip over matched word
602:                            //          text = text.substring(adjustedOffset, len);    // len is length of text before update
603:                            rem = len - foundOffset; // len is updated to length of remaining text to search
604:                            matchLocation = foundLocation + wordLen; // matchLocation is index in _doc of right edge of match
605:                            //            _current = docToSearch.createPosition(start);          // put caret at beginning of found word
606:                        } else {
607:
608:                            foundOffset -= wordLen; // skip over matched word        
609:                            rem = foundOffset; // rem is adjusted to match foundOffset
610:                            matchLocation = foundLocation; // matchLocation is index in _doc of left edge of match
611:                            //          text = text.substring(0, len);               // len is length of text after update
612:                            //            _current = docToSearch.createPosition(foundLocation);  // put caret at end of found word
613:                        }
614:                        //        _log.log("rem = " + rem);
615:                        doc.setCurrentLocation(foundLocation); // _shouldIgnore below uses reduced model
616:
617:                        //        _log.log("Finished iteration with text = " + text + "; len = " + len + "; foundLocation = " + foundLocation);
618:                        assert foundLocation > -1;
619:                        if (_shouldIgnore(foundLocation, doc))
620:                            continue;
621:
622:                        //_current = doc.createPosition(matchLocation);   // formerly doc.createPosition(...)
623:                        setPosition(matchLocation);
624:
625:                        //        System.err.println("Returning result = " + new FindResult(doc, matchLocation, wrapped, allWrapped));
626:
627:                        return new FindResult(doc, matchLocation, wrapped,
628:                                allWrapped); // return valid match
629:                    }
630:                } catch (BadLocationException e) {
631:                    throw new UnexpectedException(e);
632:                }
633:
634:                // loop fell through; search failed in doc segment
635:                return new FindResult(doc, -1, wrapped, allWrapped);
636:            }
637:
638:            /** Searches all documents following startDoc for _findWord, cycling through the documents in the direction specified
639:             *  by _isForward. If the search cycles back to doc without finding a match, performs a wrapped search on doc.
640:             *  @param startDoc  document where searching started and just failed
641:             *  @param start  location in startDoc of the document segment where search failed.
642:             *  @param len  length of the text segment where search failed.
643:             *  @return the FindResult containing the information for where we found _findWord or a dummy FindResult.
644:             */
645:            private FindResult _findNextInOtherDocs(
646:                    final OpenDefinitionsDocument startDoc, int start, int len) {
647:
648:                //    System.err.println("_findNextInOtherDocs(" + startDoc.getText() + ", " + start + ", " + len + ")");
649:
650:                boolean allWrapped = false;
651:                _doc = _isForward ? _docIterator.getNextDocument(startDoc)
652:                        : _docIterator.getPrevDocument(startDoc);
653:
654:                while (_doc != startDoc) {
655:                    if (_doc == _firstDoc)
656:                        allWrapped = true;
657:
658:                    //      System.err.println("_doc = [" + _doc.getText() + "]");
659:
660:                    //      if (_isForward) setPosition(0);
661:                    //      else setPosition(_doc.getLength());
662:
663:                    // find next match in _doc
664:                    _doc.acquireReadLock();
665:                    FindResult fr;
666:                    try {
667:                        fr = _findNextInDocSegment(_doc, 0, _doc.getLength(),
668:                                false, allWrapped);
669:                    } finally {
670:                        _doc.releaseReadLock();
671:                    }
672:
673:                    if (fr.getFoundOffset() >= 0)
674:                        return fr;
675:
676:                    //      System.err.println("Advancing from '" + _doc.getText() + "' to next doc");        
677:                    _doc = _isForward ? _docIterator.getNextDocument(_doc)
678:                            : _docIterator.getPrevDocument(_doc);
679:                    //      System.err.println("Next doc is: '" + _doc.getText() + "'");
680:                }
681:
682:                // No valid match found; perform wrapped search.  _findWrapped assumes acquireReadLock is held.
683:                startDoc.acquireReadLock();
684:                try {
685:                    return _findWrapped(startDoc, start, len, true);
686:                } // last arg is true because searching all docs has wrapped
687:                finally {
688:                    startDoc.releaseReadLock();
689:                }
690:            }
691:
692:            /** Determines whether the whole find word is found at the input position
693:             * @param doc - the document where an instance of the find word was found
694:             * @param foundOffset - the position where that instance was found
695:             * @return true if the whole word is found at foundOffset, false otherwise
696:             */
697:            private boolean wholeWordFoundAtCurrent(
698:                    OpenDefinitionsDocument doc, int foundOffset) {
699:
700:                char leftOfMatch = 0; //  forced initialization
701:                char rightOfMatch = 0; //  forced initialization
702:                int leftLoc = foundOffset - 1;
703:                int rightLoc = foundOffset + _findWord.length();
704:                boolean leftOutOfBounds = false;
705:                boolean rightOutOfBounds = false;
706:
707:                doc.acquireReadLock();
708:                try {
709:                    try {
710:                        leftOfMatch = doc.getText(leftLoc, 1).charAt(0);
711:                    } catch (BadLocationException e) {
712:                        leftOutOfBounds = true;
713:                    } catch (IndexOutOfBoundsException e) {
714:                        leftOutOfBounds = true;
715:                    }
716:                    try {
717:                        rightOfMatch = doc.getText(rightLoc, 1).charAt(0);
718:                    } catch (BadLocationException e) {
719:                        rightOutOfBounds = true;
720:                    } catch (IndexOutOfBoundsException e) {
721:                        rightOutOfBounds = true;
722:                    }
723:                } finally {
724:                    doc.releaseReadLock();
725:                }
726:
727:                if (!leftOutOfBounds && !rightOutOfBounds)
728:                    return isDelimiter(rightOfMatch)
729:                            && isDelimiter(leftOfMatch);
730:                if (!leftOutOfBounds)
731:                    return isDelimiter(leftOfMatch);
732:                if (!rightOutOfBounds)
733:                    return isDelimiter(rightOfMatch);
734:                return true;
735:            }
736:
737:            /** Determines whether a character is a delimiter (not a letter or digit) as a helper to wholeWordFoundAtCurrent
738:             * 
739:             * @param ch - a character
740:             * @return true if ch is a delimiter, false otherwise
741:             */
742:            private boolean isDelimiter(char ch) {
743:                return !Character.isLetterOrDigit(ch);
744:            }
745:
746:            /** Returns true if the currently found instance should be ignored (either because it is inside a string or comment or
747:             * because it does not match the whole word when either or both of those conditions are set to true).  Only executes 
748:             * in event thread.
749:             * @param foundOffset the location of the instance found
750:             * @param doc the current document where the instance was found
751:             * @return true if the location should be ignored, false otherwise
752:             */
753:            private boolean _shouldIgnore(int foundOffset,
754:                    OpenDefinitionsDocument odd) {
755:
756:                assert EventQueue.isDispatchThread();
757:
758:                return (_matchWholeWord && !wholeWordFoundAtCurrent(odd,
759:                        foundOffset))
760:                        || (_ignoreCommentsAndStrings && odd
761:                                .getStateAtCurrent() != ReducedModelStates.FREE);
762:            }
763:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.