KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > compare > internal > CompareFilter


1 /*******************************************************************************
2  * Copyright (c) 2000, 2006 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 package org.eclipse.compare.internal;
12
13 import com.ibm.icu.text.MessageFormat;
14 import java.util.StringTokenizer JavaDoc;
15
16 import org.eclipse.core.resources.*;
17 import org.eclipse.core.resources.IWorkspace;
18 import org.eclipse.core.runtime.IStatus;
19
20
21 public class CompareFilter {
22     private static final char[][] NO_CHAR_CHAR= new char[0][];
23     
24     private char[][] fExtraResourceFileFilters;
25     private String JavaDoc[] fExtraResourceFolderFilters;
26
27     
28     public CompareFilter() {
29         // nothing to do
30
}
31
32     /*
33      * Returns true if path matches filter, that is if path should be filtered.
34      */

35     public boolean filter(String JavaDoc path0, boolean folder, boolean isArchive) {
36         if (!folder && fExtraResourceFileFilters != null) {
37             char[] name= path0.toCharArray();
38             for (int i= 0, l= fExtraResourceFileFilters.length; i < l; i++)
39                 if (match(fExtraResourceFileFilters[i], name, true))
40                     return true;
41         }
42         if (folder && fExtraResourceFolderFilters != null) {
43             for (int i= 0, l= fExtraResourceFolderFilters.length; i < l; i++)
44                 if (fExtraResourceFolderFilters[i].equals(path0))
45                     return true;
46         }
47         return false;
48     }
49
50     public static String JavaDoc validateResourceFilters(String JavaDoc text) {
51         IWorkspace workspace= ResourcesPlugin.getWorkspace();
52         String JavaDoc[] filters= getTokens(text, ","); //$NON-NLS-1$
53
for (int i= 0; i < filters.length; i++) {
54             String JavaDoc fileName= filters[i].replace('*', 'x');
55             int resourceType= IResource.FILE;
56             int lastCharacter= fileName.length() - 1;
57             if (lastCharacter >= 0 && fileName.charAt(lastCharacter) == '/') {
58                 fileName= fileName.substring(0, lastCharacter);
59                 resourceType= IResource.FOLDER;
60             }
61             IStatus status= workspace.validateName(fileName, resourceType);
62             if (status.matches(IStatus.ERROR)) {
63                 String JavaDoc format= Utilities.getString("ComparePreferencePage.filter.invalidsegment.error"); //$NON-NLS-1$
64
return MessageFormat.format(format, new String JavaDoc[] { status.getMessage() } );
65             }
66         }
67         return null;
68     }
69     
70     public void setFilters(String JavaDoc filterSequence) {
71         char[][] filters= filterSequence != null && filterSequence.length() > 0
72         ? splitAndTrimOn(',', filterSequence.toCharArray())
73         : null;
74         if (filters == null) {
75             fExtraResourceFileFilters= null;
76             fExtraResourceFolderFilters= null;
77         } else {
78             int fileCount= 0, folderCount= 0;
79             for (int i= 0, l= filters.length; i < l; i++) {
80                 char[] f= filters[i];
81                 if (f.length == 0)
82                     continue;
83                 if (f[f.length - 1] == '/')
84                     folderCount++;
85                 else
86                     fileCount++;
87             }
88             fExtraResourceFileFilters= new char[fileCount][];
89             fExtraResourceFolderFilters= new String JavaDoc[folderCount];
90             for (int i= 0, l= filters.length; i < l; i++) {
91                 char[] f= filters[i];
92                 if (f.length == 0)
93                     continue;
94                 if (f[f.length - 1] == '/')
95                     fExtraResourceFolderFilters[--folderCount]= new String JavaDoc(subarray(f, 0, f.length - 1));
96                 else
97                     fExtraResourceFileFilters[--fileCount]= f;
98             }
99         }
100     }
101
102     /////////
103

104     private static String JavaDoc[] getTokens(String JavaDoc text, String JavaDoc separator) {
105         StringTokenizer JavaDoc tok= new StringTokenizer JavaDoc(text, separator);
106         int nTokens= tok.countTokens();
107         String JavaDoc[] res= new String JavaDoc[nTokens];
108         for (int i= 0; i < res.length; i++)
109             res[i]= tok.nextToken().trim();
110         return res;
111     }
112     
113     /**
114      * Answers true if the pattern matches the given name, false otherwise.
115      * This char[] pattern matching accepts wild-cards '*' and '?'.
116      *
117      * When not case sensitive, the pattern is assumed to already be
118      * lowercased, the name will be lowercased character per character as
119      * comparing. If name is null, the answer is false. If pattern is null, the
120      * answer is true if name is not null. <br><br>For example:
121      * <ol>
122      * <li>
123      *
124      * <pre>
125      * pattern = { '?', 'b', '*' } name = { 'a', 'b', 'c' , 'd' } isCaseSensitive = true result => true
126      * </pre>
127      *
128      *
129      * </li>
130      * <li>
131      *
132      * <pre>
133      * pattern = { '?', 'b', '?' } name = { 'a', 'b', 'c' , 'd' } isCaseSensitive = true result => false
134      * </pre>
135      *
136      *
137      * </li>
138      * <li>
139      *
140      * <pre>
141      * pattern = { 'b', '*' } name = { 'a', 'b', 'c' , 'd' } isCaseSensitive = true result => false
142      * </pre>
143      *
144      *
145      * </li>
146      * </ol>
147      *
148      * @param pattern
149      * the given pattern
150      * @param name
151      * the given name
152      * @param isCaseSensitive
153      * flag to know whether or not the matching should be case
154      * sensitive
155      * @return true if the pattern matches the given name, false otherwise
156      */

157     private boolean match(char[] pattern, char[] name, boolean isCaseSensitive) {
158         if (name == null)
159             return false; // null name cannot match
160
if (pattern == null)
161             return true; // null pattern is equivalent to '*'
162
return match(pattern, 0, pattern.length, name, 0, name.length, isCaseSensitive);
163     }
164
165     /**
166      * Answers true if the a sub-pattern matches the subpart of the given name,
167      * false otherwise. char[] pattern matching, accepting wild-cards '*' and
168      * '?'. Can match only subset of name/pattern. end positions are
169      * non-inclusive. The subpattern is defined by the patternStart and
170      * pattternEnd positions. When not case sensitive, the pattern is assumed
171      * to already be lowercased, the name will be lowercased character per
172      * character as comparing. <br><br>For example:
173      * <ol>
174      * <li>
175      *
176      * <pre>
177      * pattern = { '?', 'b', '*' } patternStart = 1 patternEnd = 3 name = { 'a', 'b', 'c' , 'd' } nameStart = 1 nameEnd = 4 isCaseSensitive = true result => true
178      * </pre>
179      *
180      *
181      * </li>
182      * <li>
183      *
184      * <pre>
185      * pattern = { '?', 'b', '*' } patternStart = 1 patternEnd = 2 name = { 'a', 'b', 'c' , 'd' } nameStart = 1 nameEnd = 2 isCaseSensitive = true result => false
186      * </pre>
187      *
188      *
189      * </li>
190      * </ol>
191      *
192      * @param pattern
193      * the given pattern
194      * @param patternStart
195      * the given pattern start
196      * @param patternEnd
197      * the given pattern end
198      * @param name
199      * the given name
200      * @param nameStart
201      * the given name start
202      * @param nameEnd
203      * the given name end
204      * @param isCaseSensitive
205      * flag to know if the matching should be case sensitive
206      * @return true if the a sub-pattern matches the subpart of the given name,
207      * false otherwise
208      */

209     private boolean match(char[] pattern, int patternStart, int patternEnd, char[] name, int nameStart, int nameEnd,
210             boolean isCaseSensitive) {
211         if (name == null)
212             return false; // null name cannot match
213
if (pattern == null)
214             return true; // null pattern is equivalent to '*'
215
int iPattern= patternStart;
216         int iName= nameStart;
217         if (patternEnd < 0)
218             patternEnd= pattern.length;
219         if (nameEnd < 0)
220             nameEnd= name.length;
221         /* check first segment */
222         char patternChar= 0;
223         while ((iPattern < patternEnd) && (patternChar= pattern[iPattern]) != '*') {
224             if (iName == nameEnd)
225                 return false;
226             if (patternChar != (isCaseSensitive ? name[iName] : Character.toLowerCase(name[iName])) && patternChar != '?') {
227                 return false;
228             }
229             iName++;
230             iPattern++;
231         }
232         /* check sequence of star+segment */
233         int segmentStart;
234         if (patternChar == '*') {
235             segmentStart= ++iPattern; // skip star
236
} else {
237             segmentStart= 0; // force iName check
238
}
239         int prefixStart= iName;
240         checkSegment : while (iName < nameEnd) {
241             if (iPattern == patternEnd) {
242                 iPattern= segmentStart; // mismatch - restart current segment
243
iName= ++prefixStart;
244                 continue checkSegment;
245             }
246             /* segment is ending */
247             if ((patternChar= pattern[iPattern]) == '*') {
248                 segmentStart= ++iPattern; // skip start
249
if (segmentStart == patternEnd) {
250                     return true;
251                 }
252                 prefixStart= iName;
253                 continue checkSegment;
254             }
255             /* check current name character */
256             if ((isCaseSensitive ? name[iName] : Character.toLowerCase(name[iName])) != patternChar && patternChar != '?') {
257                 iPattern= segmentStart; // mismatch - restart current segment
258
iName= ++prefixStart;
259                 continue checkSegment;
260             }
261             iName++;
262             iPattern++;
263         }
264         return (segmentStart == patternEnd) || (iName == nameEnd && iPattern == patternEnd)
265                 || (iPattern == patternEnd - 1 && pattern[iPattern] == '*');
266     }
267
268     /**
269      * Return a new array which is the split of the given array using the given
270      * divider and triming each subarray to remove whitespaces equals to ' '.
271      * <br><br>For example:
272      * <ol>
273      * <li>
274      *
275      * <pre>
276      * divider = 'b' array = { 'a' , 'b', 'b', 'a', 'b', 'a' } result => { { 'a' }, { }, { 'a' }, { 'a' } }
277      * </pre>
278      *
279      *
280      * </li>
281      * <li>
282      *
283      * <pre>
284      * divider = 'c' array = { 'a' , 'b', 'b', 'a', 'b', 'a' } result => { { 'a', 'b', 'b', 'a', 'b', 'a' } }
285      * </pre>
286      *
287      *
288      * </li>
289      * <li>
290      *
291      * <pre>
292      * divider = 'b' array = { 'a' , ' ', 'b', 'b', 'a', 'b', 'a' } result => { { 'a' }, { }, { 'a' }, { 'a' } }
293      * </pre>
294      *
295      *
296      * </li>
297      * <li>
298      *
299      * <pre>
300      * divider = 'c' array = { ' ', ' ', 'a' , 'b', 'b', 'a', 'b', 'a', ' ' } result => { { 'a', 'b', 'b', 'a', 'b', 'a' } }
301      * </pre>
302      *
303      *
304      * </li>
305      * </ol>
306      *
307      * @param divider
308      * the given divider
309      * @param array
310      * the given array
311      * @return a new array which is the split of the given array using the
312      * given divider and triming each subarray to remove whitespaces
313      * equals to ' '
314      */

315     private char[][] splitAndTrimOn(char divider, char[] array) {
316         int length= array == null ? 0 : array.length;
317         if (length == 0)
318             return NO_CHAR_CHAR;
319         int wordCount= 1;
320         for (int i= 0; i < length; i++)
321             if (array[i] == divider)
322                 wordCount++;
323         char[][] split= new char[wordCount][];
324         int last= 0, currentWord= 0;
325         for (int i= 0; i < length; i++) {
326             if (array[i] == divider) {
327                 int start= last, end= i - 1;
328                 while (start < i && array[start] == ' ')
329                     start++;
330                 while (end > start && array[end] == ' ')
331                     end--;
332                 split[currentWord]= new char[end - start + 1];
333                 System.arraycopy(array, start, split[currentWord++], 0, end - start + 1);
334                 last= i + 1;
335             }
336         }
337         int start= last, end= length - 1;
338         while (start < length && array[start] == ' ')
339             start++;
340         while (end > start && array[end] == ' ')
341             end--;
342         split[currentWord]= new char[end - start + 1];
343         System.arraycopy(array, start, split[currentWord++], 0, end - start + 1);
344         return split;
345     }
346
347     /**
348      * Answers a new array which is a copy of the given array starting at the
349      * given start and ending at the given end. The given start is inclusive
350      * and the given end is exclusive. Answers null if start is greater than
351      * end, if start is lower than 0 or if end is greater than the length of
352      * the given array. If end equals -1, it is converted to the array length.
353      * <br><br>For example:
354      * <ol>
355      * <li>
356      *
357      * <pre>
358      * array = { 'a' , 'b' } start = 0 end = 1 result => { 'a' }
359      * </pre>
360      *
361      *
362      * </li>
363      * <li>
364      *
365      * <pre>
366      * array = { 'a', 'b' } start = 0 end = -1 result => { 'a' , 'b' }
367      * </pre>
368      *
369      *
370      * </li>
371      * </ol>
372      *
373      * @param array
374      * the given array
375      * @param start
376      * the given starting index
377      * @param end
378      * the given ending index
379      * @return a new array which is a copy of the given array starting at the
380      * given start and ending at the given end
381      * @exception NullPointerException
382      * if the given array is null
383      */

384     private char[] subarray(char[] array, int start, int end) {
385         if (end == -1)
386             end= array.length;
387         if (start > end)
388             return null;
389         if (start < 0)
390             return null;
391         if (end > array.length)
392             return null;
393         char[] result= new char[end - start];
394         System.arraycopy(array, start, result, 0, end - start);
395         return result;
396     }
397 }
398
Popular Tags