KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > ui > internal > console > ConsolePatternMatcher


1 /*******************************************************************************
2  * Copyright (c) 2000, 2007 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11
12 package org.eclipse.ui.internal.console;
13
14 import java.util.ArrayList JavaDoc;
15 import java.util.Iterator JavaDoc;
16 import java.util.regex.Matcher JavaDoc;
17 import java.util.regex.Pattern JavaDoc;
18
19 import org.eclipse.core.runtime.IProgressMonitor;
20 import org.eclipse.core.runtime.IStatus;
21 import org.eclipse.core.runtime.Status;
22 import org.eclipse.core.runtime.jobs.Job;
23 import org.eclipse.jface.text.BadLocationException;
24 import org.eclipse.jface.text.DocumentEvent;
25 import org.eclipse.jface.text.IDocument;
26 import org.eclipse.jface.text.IDocumentListener;
27 import org.eclipse.ui.console.ConsolePlugin;
28 import org.eclipse.ui.console.IPatternMatchListener;
29 import org.eclipse.ui.console.PatternMatchEvent;
30 import org.eclipse.ui.console.TextConsole;
31
32 public class ConsolePatternMatcher implements IDocumentListener {
33
34     private MatchJob fMatchJob = new MatchJob();
35
36     /**
37      * Collection of compiled pattern match listeners
38      */

39     private ArrayList JavaDoc fPatterns = new ArrayList JavaDoc();
40
41     private TextConsole fConsole;
42
43     private boolean fFinalMatch;
44
45     private boolean fScheduleFinal;
46
47     public ConsolePatternMatcher(TextConsole console) {
48         fConsole = console;
49     }
50
51     private class MatchJob extends Job {
52         MatchJob() {
53             super("Match Job"); //$NON-NLS-1$
54
setSystem(true);
55         }
56
57         /*
58          * (non-Javadoc)
59          *
60          * @see org.eclipse.core.runtime.jobs.Job#run(org.eclipse.core.runtime.IProgressMonitor)
61          */

62         protected IStatus run(IProgressMonitor monitor) {
63             IDocument doc = fConsole.getDocument();
64             String JavaDoc text = null;
65             int prevBaseOffset = -1;
66             if (doc != null && !monitor.isCanceled()) {
67                 int endOfSearch = doc.getLength();
68                 int indexOfLastChar = endOfSearch;
69                 if (indexOfLastChar > 0) {
70                     indexOfLastChar--;
71                 }
72                 int lastLineToSearch = 0;
73                 int offsetOfLastLineToSearch = 0;
74                 try {
75                     lastLineToSearch = doc.getLineOfOffset(indexOfLastChar);
76                     offsetOfLastLineToSearch = doc.getLineOffset(lastLineToSearch);
77                 } catch (BadLocationException e) {
78                     // perhaps the buffer was re-set
79
return Status.OK_STATUS;
80                 }
81                 for (int i = 0; i < fPatterns.size(); i++) {
82                     if (monitor.isCanceled()) {
83                         break;
84                     }
85                     CompiledPatternMatchListener notifier = (CompiledPatternMatchListener) fPatterns.get(i);
86                     int baseOffset = notifier.end;
87                     int lengthToSearch = endOfSearch - baseOffset;
88                     if (lengthToSearch > 0) {
89                         try {
90                             if (prevBaseOffset != baseOffset) {
91                                 // reuse the text string if possible
92
text = doc.get(baseOffset, lengthToSearch);
93                             }
94                             Matcher JavaDoc reg = notifier.pattern.matcher(text);
95                             Matcher JavaDoc quick = null;
96                             if (notifier.qualifier != null) {
97                                 quick = notifier.qualifier.matcher(text);
98                             }
99                             int startOfNextSearch = 0;
100                             int endOfLastMatch = -1;
101                             int lineOfLastMatch = -1;
102                             while ((startOfNextSearch < lengthToSearch) && !monitor.isCanceled()) {
103                                 if (quick != null) {
104                                     if (quick.find(startOfNextSearch)) {
105                                         // start searching on the beginning
106
// of the line where the potential
107
// match was found, or after the
108
// last match on the same line
109
int matchLine = doc.getLineOfOffset(baseOffset + quick.start());
110                                         if (lineOfLastMatch == matchLine) {
111                                             startOfNextSearch = endOfLastMatch;
112                                         } else {
113                                             startOfNextSearch = doc.getLineOffset(matchLine) - baseOffset;
114                                         }
115                                     } else {
116                                         startOfNextSearch = lengthToSearch;
117                                     }
118                                 }
119                                 if (startOfNextSearch < 0) {
120                                     startOfNextSearch = 0;
121                                 }
122                                 if (startOfNextSearch < lengthToSearch) {
123                                     if (reg.find(startOfNextSearch)) {
124                                         endOfLastMatch = reg.end();
125                                         lineOfLastMatch = doc.getLineOfOffset(baseOffset + endOfLastMatch - 1);
126                                         int regStart = reg.start();
127                                         IPatternMatchListener listener = notifier.listener;
128                                         if (listener != null && !monitor.isCanceled()) {
129                                             listener.matchFound(new PatternMatchEvent(fConsole, baseOffset + regStart, endOfLastMatch - regStart));
130                                         }
131                                         startOfNextSearch = endOfLastMatch;
132                                     } else {
133                                         startOfNextSearch = lengthToSearch;
134                                     }
135                                 }
136                             }
137                             // update start of next search to the last line
138
// searched
139
// or the end of the last match if it was on the
140
// line that
141
// was last searched
142
if (lastLineToSearch == lineOfLastMatch) {
143                                 notifier.end = baseOffset + endOfLastMatch;
144                             } else {
145                                 notifier.end = offsetOfLastLineToSearch;
146                             }
147                         } catch (BadLocationException e) {
148                             ConsolePlugin.log(e);
149                         }
150                     }
151                     prevBaseOffset = baseOffset;
152                 }
153             }
154
155             if (fFinalMatch) {
156                 disconnect();
157                 fConsole.matcherFinished();
158             } else if (fScheduleFinal) {
159                 fFinalMatch = true;
160                 schedule();
161             }
162
163             return Status.OK_STATUS;
164         }
165
166         public boolean belongsTo(Object JavaDoc family) {
167             return family == fConsole;
168         }
169         
170         
171     }
172
173     private class CompiledPatternMatchListener {
174         Pattern JavaDoc pattern;
175
176         Pattern JavaDoc qualifier;
177
178         IPatternMatchListener listener;
179
180         int end = 0;
181
182         CompiledPatternMatchListener(Pattern JavaDoc pattern, Pattern JavaDoc qualifier, IPatternMatchListener matchListener) {
183             this.pattern = pattern;
184             this.listener = matchListener;
185             this.qualifier = qualifier;
186         }
187
188         public void dispose() {
189             listener.disconnect();
190             pattern = null;
191             qualifier = null;
192             listener = null;
193         }
194     }
195
196     /**
197      * Adds the given pattern match listener to this console. The listener will
198      * be connected and receive match notifications.
199      *
200      * @param matchListener
201      * the pattern match listener to add
202      */

203     public void addPatternMatchListener(IPatternMatchListener matchListener) {
204         synchronized (fPatterns) {
205             
206             // check for dups
207
for (Iterator JavaDoc iter = fPatterns.iterator(); iter.hasNext();) {
208                 CompiledPatternMatchListener element = (CompiledPatternMatchListener) iter.next();
209                 if (element.listener == matchListener) {
210                     return;
211                 }
212             }
213             
214             if (matchListener == null || matchListener.getPattern() == null) {
215                 throw new IllegalArgumentException JavaDoc("Pattern cannot be null"); //$NON-NLS-1$
216
}
217
218             Pattern JavaDoc pattern = Pattern.compile(matchListener.getPattern(), matchListener.getCompilerFlags());
219             String JavaDoc qualifier = matchListener.getLineQualifier();
220             Pattern JavaDoc qPattern = null;
221             if (qualifier != null) {
222                 qPattern = Pattern.compile(qualifier, matchListener.getCompilerFlags());
223             }
224             CompiledPatternMatchListener notifier = new CompiledPatternMatchListener(pattern, qPattern, matchListener);
225             fPatterns.add(notifier);
226             matchListener.connect(fConsole);
227             fMatchJob.schedule();
228         }
229     }
230
231     /**
232      * Removes the given pattern match listener from this console. The listener
233      * will be disconnected and will no longer receive match notifications.
234      *
235      * @param matchListener
236      * the pattern match listener to remove.
237      */

238     public void removePatternMatchListener(IPatternMatchListener matchListener) {
239         synchronized (fPatterns) {
240             for (Iterator JavaDoc iter = fPatterns.iterator(); iter.hasNext();) {
241                 CompiledPatternMatchListener element = (CompiledPatternMatchListener) iter.next();
242                 if (element.listener == matchListener) {
243                     iter.remove();
244                     matchListener.disconnect();
245                 }
246             }
247         }
248     }
249
250     public void disconnect() {
251         fMatchJob.cancel();
252         synchronized (fPatterns) {
253             Iterator JavaDoc iterator = fPatterns.iterator();
254             while (iterator.hasNext()) {
255                 CompiledPatternMatchListener notifier = (CompiledPatternMatchListener) iterator.next();
256                 notifier.dispose();
257             }
258             fPatterns.clear();
259         }
260     }
261
262     /*
263      * (non-Javadoc)
264      *
265      * @see org.eclipse.jface.text.IDocumentListener#documentAboutToBeChanged(org.eclipse.jface.text.DocumentEvent)
266      */

267     public void documentAboutToBeChanged(DocumentEvent event) {
268     }
269
270     /*
271      * (non-Javadoc)
272      *
273      * @see org.eclipse.jface.text.IDocumentListener#documentChanged(org.eclipse.jface.text.DocumentEvent)
274      */

275     public void documentChanged(DocumentEvent event) {
276         if (event.fLength > 0) {
277             synchronized (fPatterns) {
278                 if (event.fDocument.getLength() == 0) {
279                     // document has been cleared, reset match listeners
280
Iterator JavaDoc iter = fPatterns.iterator();
281                     while (iter.hasNext()) {
282                         CompiledPatternMatchListener notifier = (CompiledPatternMatchListener) iter.next();
283                         notifier.end = 0;
284                     }
285                 } else {
286                     if (event.fOffset == 0) {
287                         //document was trimmed
288
Iterator JavaDoc iter = fPatterns.iterator();
289                         while (iter.hasNext()) {
290                             CompiledPatternMatchListener notifier = (CompiledPatternMatchListener) iter.next();
291                             notifier.end = notifier.end > event.fLength ? notifier.end-event.fLength : 0;
292                         }
293                     }
294                 }
295             }
296         }
297         fMatchJob.schedule();
298     }
299
300     
301     public void forceFinalMatching() {
302         fScheduleFinal = true;
303         fMatchJob.schedule();
304     }
305
306 }
307
Popular Tags