KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > search > types > TextType


1 /*
2  * The contents of this file are subject to the terms of the Common Development
3  * and Distribution License (the License). You may not use this file except in
4  * compliance with the License.
5  *
6  * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
7  * or http://www.netbeans.org/cddl.txt.
8  *
9  * When distributing Covered Code, include this CDDL Header Notice in each file
10  * and include the License file at http://www.netbeans.org/cddl.txt.
11  * If applicable, add the following below the CDDL Header, with the fields
12  * enclosed by brackets [] replaced by your own identifying information:
13  * "Portions Copyrighted [year] [name of copyright owner]"
14  *
15  * The Original Software is NetBeans. The Initial Developer of the Original
16  * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19
20
21 package org.netbeans.modules.search.types;
22
23 import java.util.regex.Pattern JavaDoc;
24 import java.util.regex.PatternSyntaxException JavaDoc;
25 import java.util.regex.Matcher JavaDoc;
26
27
28 /**
29  * Abstract search type for searching in text.
30  * The text can be searched either for a substring or for a regular expression
31  * pattern. When a {@linkplain #setMatchString substring is set},
32  * a previously {@linkplain #setRe set regular expression}, is cleared
33  * and vice versa.
34  *
35  * @see #match match(String)
36  * @author Petr Kuzel
37  * @author Marian Petras
38  */

39 public abstract class TextType extends DataObjectType {
40
41     private static final long serialVersionUID = 3L;
42     //private static final long serialVersionUID = -3260233821452714775L;
43

44     /** set of word separator characters */
45     private static final String JavaDoc WORD_SEPARATORS
46             = " \t,;.:+-*/\\()[]{}<>=&|\"\'`~!?@#%^\n\r"; //NOI18N
47

48     /** flag - be case-sensitive when searching? */
49     protected boolean caseSensitive;
50     /**
51      * flag - match only whole words?
52      *
53      * @see #setWholeWords
54      */

55     protected boolean wholeWords;
56
57     /**
58      * uppercased search pattern - substring.
59      * It is used for case-insensitive searching.
60      *
61      * @see #matchString
62      */

63     protected transient String JavaDoc ciMatchString;
64     /**
65      * search pattern - substring
66      *
67      * @see #reString
68      */

69     protected String JavaDoc matchString;
70     /**
71      * search pattern - regular expression
72      *
73      * @see #matchString
74      */

75     protected String JavaDoc reString;
76     /**
77      * compiled search pattern - regular expression
78      *
79      * @see #reString
80      */

81     protected transient Pattern JavaDoc pattern;
82
83     private transient Matcher JavaDoc matcher;
84
85     /** reads a serialized form - used during deserialization */
86     private void readObject(java.io.ObjectInputStream JavaDoc ois)
87             throws java.io.IOException JavaDoc, ClassNotFoundException JavaDoc {
88         ois.defaultReadObject();
89         if (!caseSensitive && matchString != null) {
90             ciMatchString = matchString.toUpperCase();
91         }
92         if (reString != null) {
93             setRe(reString);
94         }
95     }
96
97     // Match methods
98
/**
99      * Checks whether the specified string matches the specified pattern.
100      * If a substring is set, the text is searched for the substring,
101      * otherwise the text is searched for a regular expression.
102      *
103      * @param text text to check agains the pattern
104      * @return <code>true</code> if the text matches the pattern;
105      * <code>false</code> otherwise
106      * @see #setMatchString
107      * @see #setRe
108      */

109     protected boolean match(String JavaDoc text) {
110         if (matchString != null) {
111             
112             if (text.length() < matchString.length()) {
113                 return false;
114             }
115             
116             if (!caseSensitive) {
117                 text = text.toUpperCase();
118             }
119             int fromIndex = 1;
120             int fromIndexMax = text.length() - matchString.length() + 1;
121             int matchIndex;
122             
123             do {
124                 matchIndex = matchString(text, fromIndex);
125                 fromIndex = Math.abs(matchIndex) + 1;
126             } while ((matchIndex < 0) && (fromIndex <= fromIndexMax));
127             
128             return matchIndex > 0;
129         } else {
130             return matchRE(text);
131         }
132     }
133
134     /**
135      * Checks whether the specified string matches the specified regular
136      * expression.
137      *
138      * @param line text to check agains the pattern
139      * @return <code>true</code> if the text matches the pattern;
140      * <code>false</code> otherwise
141      * @see #setRe
142      */

143     protected boolean matchRE(String JavaDoc line) {
144         matcher = pattern.matcher(line);
145         return matcher.find();
146     }
147
148     /** Returs matches that was used by last matchRE operation. */
149     protected Matcher JavaDoc getMatcher() {
150         return matcher;
151     }
152
153     /**
154      * Searches part of text for a substring.
155      *
156      * @param text text to search
157      * - must be all in uppercase for case-insensitive search
158      * @param fromIndex offset to start searching at
159      * (first character &sim; {@code 1})
160      * @return position of the substring within the (whole) text, starting from
161      * {@code 1},<br />
162      * {@code 0} if the text does not contain the substring,<br />
163      * or negative value if the string is found but it is not bound
164      * by word separators and the <em>whole words</em> condition is
165      * required - absolute value if the returned value then points
166      * to the position of the found string, starting from {@code 1}
167      * @see #setMatchString
168      */

169     protected int matchString(String JavaDoc text, int fromIndex) {
170         assert fromIndex >= 1;
171         
172         int index = text.indexOf(caseSensitive ? matchString : ciMatchString,
173                                  fromIndex - 1);
174         
175         int retValue = index + 1;
176         
177         int boundaryIndex;
178         if (wholeWords //test "whole words only" condition
179
&& (retValue != 0)
180             && ((((boundaryIndex = index - 1) >= 0)
181                 && WORD_SEPARATORS.indexOf(text.charAt(boundaryIndex)) < 0)
182                ||
183                (((boundaryIndex = index + matchString.length()) < text.length())
184                 && WORD_SEPARATORS.indexOf(text.charAt(boundaryIndex)) < 0))) {
185             retValue = -retValue;
186         }
187
188         return retValue;
189     }
190
191
192     // Properties
193
/** Getter for <code>matchString</code> property. */
194     /**
195      * Returns a substring to search for.
196      *
197      * @return substring to search for; or an empty string if a regular
198      * expression will be used for searching
199      * @see #setMatchString setMatchString(...)
200      */

201     public String JavaDoc getMatchString() {
202         if (matchString == null) {
203             return ""; // NOI18N
204
} else {
205             return matchString;
206         }
207     }
208
209     /**
210      * Sets a substring to search for.
211      * Calling this method clears a previously set regular expression
212      * (see {@link #setRe setRe(...)}), unless an exception is thrown.
213      *
214      * @param substring substring to search for
215      * @exception java.lang.IllegalArgumentException
216      * if the specified substring is <code>null</code>
217      */

218     public void setMatchString(String JavaDoc substring) {
219         if (substring == null) {
220             setValid(false);
221             throw new IllegalArgumentException JavaDoc();
222         }
223
224         if (substring.length() == 0) {
225             substring = null;
226         } else if (!caseSensitive) {
227             ciMatchString = substring.toUpperCase();
228         }
229         this.matchString = substring;
230         pattern = null;
231         reString = null;
232
233         setValid(substring != null);
234     }
235
236     /**
237      * Returns a regular expression that will be used for searching.
238      *
239      * @return regular expression; or an empty string if text will be searched
240      * for a substring (not for a regular expression)
241      * @see #setRe setRe(...)
242      */

243     public String JavaDoc getRe() {
244         if (reString == null) {
245             return ""; //NOI18N
246
} else {
247             return reString;
248         }
249     }
250     
251     /**
252      */

253     public String JavaDoc getMatchTemplateDescr() {
254         return (matchString != null) ? matchString : reString;
255     }
256     
257     /**
258      */

259     public Pattern JavaDoc getSearchPattern() {
260         if (pattern == null) {
261             assert matchString != null;
262             
263             String JavaDoc quoted = quoteString(matchString);
264             String JavaDoc regexp;
265             if (!wholeWords) {
266                 regexp = quoted;
267             } else {
268                 StringBuilder JavaDoc buf = new StringBuilder JavaDoc(quoted.length() + 6);
269                 if (wholeWords) {
270                     buf.append("\\b"); //NOI18N
271
}
272                 buf.append(quoted);
273                 if (wholeWords) {
274                     buf.append("\\b"); //NOI18N
275
}
276                 regexp = buf.toString();
277             }
278             
279             int flags = Pattern.UNICODE_CASE;
280             if (!caseSensitive) {
281                 flags |= Pattern.CASE_INSENSITIVE;
282             }
283             
284             pattern = Pattern.compile(regexp, flags);
285         }
286         return pattern;
287     }
288     
289     /** */
290     private static String JavaDoc quoteString(String JavaDoc string) {
291         if (string.length() == 0) {
292             return string;
293         }
294
295         StringBuilder JavaDoc buf;
296
297         int startIndex = 0;
298         int endIndex = string.indexOf('\\'); //NOI18N
299

300         if (endIndex == -1) {
301             buf = new StringBuilder JavaDoc(string.length() + 4);
302             buf.append("\\Q").append(string).append("\\E"); //NOI18N
303
} else {
304             buf = new StringBuilder JavaDoc(string.length() + 16);
305             do {
306                 if (endIndex != startIndex) {
307                     buf.append("\\Q"); //NOI18N
308
buf.append(string.substring(startIndex, endIndex));
309                     buf.append("\\E"); //NOI18N
310
}
311                 buf.append('\\').append('\\');
312                 startIndex = endIndex + 1;
313                 endIndex = string.indexOf('\\', startIndex);
314             } while (endIndex != -1);
315             if (startIndex != string.length()) {
316                 buf.append("\\Q"); //NOI18N
317
buf.append(string.substring(startIndex));
318                 buf.append("\\E"); //NOI18N
319
}
320         }
321         return buf.toString();
322     }
323
324     /**
325      * Sets a regular expresion to use for searching.
326      * Calling this method clears a previously set substring
327      * (see {@link #setMatchString setMatchString(...)}), unless an exception
328      * is thrown.
329      *
330      * @param exp regular expression to use
331      * @exception java.lang.IllegalArgumentException
332      * if the passed string was <code>null</code> or if it was not
333      * a regular expression accepted by class
334      * {@link java.util.regex.Pattern Pattern}
335      */

336     public void setRe(String JavaDoc re) {
337         setReImpl(re);
338     }
339
340     /**
341      * Sets a regular expresion to use for searching.
342      *
343      * @param exp regular expression to use
344      * @exception java.lang.IllegalArgumentException
345      * if the passed string was <code>null</code> or if it was not
346      * a regular expression accepted by class
347      * {@link java.util.regex.Pattern Pattern}
348      */

349     private void setReImpl(String JavaDoc exp) {
350         if (exp == null) {
351             setValid(false);
352             throw new IllegalArgumentException JavaDoc();
353         }
354
355         if (exp.length() == 0) {
356             exp = null;
357         } else {
358             try {
359                 pattern = Pattern.compile(exp);
360             } catch (PatternSyntaxException JavaDoc ex) {
361                 setValid(false);
362                 throw new IllegalArgumentException JavaDoc();
363             }
364         }
365         reString = exp;
366         matchString = null;
367
368         setValid(exp != null);
369     }
370
371     /**
372      * Will searching be case-sensitive?
373      *
374      * @return <code>true</code> if case-sensitive search will be used;
375      * <code>false</code> otherwise
376      */

377     public boolean isCaseSensitive() {
378         return caseSensitive;
379     }
380
381     /**
382      * Specifies whether case-sensitive or case-insensitive search should be
383      * used.
384      *
385      * @param caseSensitive use <code>true</code> for case-sensitive,
386      * <code>false</code> for case-insensitive
387      */

388     public void setCaseSensitive(boolean caseSensitive) {
389         if (caseSensitive == this.caseSensitive) {
390             return;
391         }
392         this.caseSensitive = caseSensitive;
393
394         if (matchString != null) {
395             ciMatchString = caseSensitive ? null : matchString.toUpperCase();
396         }
397     }
398
399     /**
400      * Are only whole words allowed in matching results?
401      *
402      * @return <code>true</code> if only whole words are allowed;
403      * <code>false</code> if parts are allowed, too
404      */

405     public boolean getWholeWords() {
406         return wholeWords;
407     }
408
409     /**
410      * Specifies whether only whole words are allowed in matching results.
411      *
412      * @param wholeWords use <code>true</code> if only whole words are allowed;
413      * <code>false</code> if parts are allowed, too
414      */

415     public void setWholeWords(boolean wholeWords) {
416         if (wholeWords == this.wholeWords) {
417             return;
418         }
419         this.wholeWords = wholeWords;
420     }
421
422 }
423
Popular Tags