Statistics
| Revision:

root / trunk / libraries / libUIComponent / src / org / gvsig / gui / beans / swing / jComboBoxItemsSeeker / BinarySearchUsingFirstCharacters.java @ 13136

History | View | Annotate | Download (15.5 KB)

1
package org.gvsig.gui.beans.swing.jComboBoxItemsSeeker;
2

    
3
import java.util.ArrayList;
4
import java.util.Arrays;
5
import java.util.Comparator;
6
import java.util.List;
7
import java.util.Vector;
8

    
9

    
10
/* gvSIG. Sistema de Informaci?n Geogr?fica de la Generalitat Valenciana
11
 *
12
 * Copyright (C) 2004 IVER T.I. and Generalitat Valenciana.
13
 *
14
 * This program is free software; you can redistribute it and/or
15
 * modify it under the terms of the GNU General Public License
16
 * as published by the Free Software Foundation; either version 2
17
 * of the License, or (at your option) any later version.
18
 *
19
 * This program is distributed in the hope that it will be useful,
20
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22
 * GNU General Public License for more details.
23
 *
24
 * You should have received a copy of the GNU General Public License
25
 * along with this program; if not, write to the Free Software
26
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,USA.
27
 *
28
 * For more information, contact:
29
 *
30
 *  Generalitat Valenciana
31
 *   Conselleria d'Infraestructures i Transport
32
 *   Av. Blasco Ib??ez, 50
33
 *   46010 VALENCIA
34
 *   SPAIN
35
 *
36
 *      +34 963862235
37
 *   gvsig@gva.es
38
 *      www.gvsig.gva.es
39
 *
40
 *    or
41
 *
42
 *   IVER T.I. S.A
43
 *   Salamanca 50
44
 *   46005 Valencia
45
 *   Spain
46
 *
47
 *   +34 963163400
48
 *   dac@iver.es
49
 */
50

    
51
/**
52
 * This class has static methods that return items that their beginning text value matches with a text pattern. <br>
53
 * It's necessary that items of the parameter array (Vector) were sort ordered according to their text value. <br>
54
 * Supports Vectors with and without repeated items.
55
 * 
56
 * There are four methods, that are a modification of a binary search algorithm of search, getting a rank of items:
57
 * <ul>
58
 * <li>Considering case sensitive in the search.</li>
59
 * <li>Ignoring case sensitive in the search.</li>
60
 * <li>Considering case sensitive in the search and an object which implements the Comparable interface</li>
61
 * <li>Ignoring case sensitive in the search, but yes an objecth which implements the Comparable interface</li>
62
 * </ul>
63
 * 
64
 * This class is a copy of a class with the same name located in <i>libIverUtiles</i>
65
 * 
66
 * @author Pablo Piqueras Bartolom? (p_queras@hotmail.com)
67
 */
68
public class BinarySearchUsingFirstCharacters {
69
        /**
70
         * This method should be used when is wanted to distinguish small letters from capital letters during the search.
71
         *   
72
         * It's necessary that all items of the array implement the {@link Comparable} interface.<br>
73
         * And it's also necessary that the value returned by the <i>toString()</i> method of each item (supposing 
74
         *   they inherit from Object) would be the expected value user saw (that would be used to compare the items).
75
         *   
76
         * @param text java.lang.String
77
         * @param sortOrderedItems java.util.Vector
78
         */
79
        public synchronized static List doSearchConsideringCaseSensitive(String text, Vector sortOrderedItems) {
80
                int currentIteration = 0;
81
                int size = sortOrderedItems.size();
82
                int maxNumberOfIterations = (int) MathExtensionReduced.log2(size);
83
                int lowIndex = 0;
84
                int highIndex = sortOrderedItems.size() - 1;
85
                int mIndx;
86
                
87
                while ((lowIndex <= highIndex) && (currentIteration <= maxNumberOfIterations)) {
88
                        mIndx = ( lowIndex + highIndex ) / 2;
89
                        
90
                        if ( sortOrderedItems.get( mIndx ).toString().startsWith( text ) ) {
91
                                lowIndex = highIndex = mIndx;
92
                                highIndex ++;
93
                                
94
                                // Expand the rank to up
95
                                while ( ( highIndex < size ) && ( sortOrderedItems.get( highIndex ).toString().startsWith( text ) ) ) {
96
                                        highIndex ++;
97
                                }
98

    
99
                                // Expand the rank to down
100
                                while ( ( (lowIndex - 1) > -1 ) && ( sortOrderedItems.get( (lowIndex - 1) ).toString().startsWith( text ) ) ) {
101
                                        lowIndex --;
102
                                }
103

    
104
                                // It's possible that items with different case, should be between the same case, then this item will be added individually:
105
                                List list = new Vector(sortOrderedItems.subList(lowIndex, highIndex));
106
                                
107
                                // Expand to down
108
                                lowIndex --;
109
                                while ( ( lowIndex > -1 ) && ( sortOrderedItems.get( (lowIndex ) ).toString().toLowerCase().startsWith( text.toLowerCase() ) ) ) {
110
                                        if (sortOrderedItems.get( lowIndex ).toString().startsWith( text )) {
111
                                                list.add(0, sortOrderedItems.get( lowIndex ));
112
                                        }
113
                                        
114
                                        lowIndex --;
115
                                }
116
                                
117
                                // Expand to up
118
                                while ( ( highIndex < size ) && ( sortOrderedItems.get( highIndex ).toString().toLowerCase().startsWith( text.toLowerCase() ) ) ) {
119
                                        if (sortOrderedItems.get( highIndex ).toString().startsWith( text )) {                                                
120
                                                list.add(list.size(), sortOrderedItems.get( highIndex ));
121
                                        }
122
                                        
123
                                        highIndex ++;
124
                                }
125
                                
126
                                // Returns all items in the rank
127
                                return list; // Breaks the loop
128
                        }
129
                        else {
130
                                if ( sortOrderedItems.get( mIndx ).toString().compareTo( text ) > 0 ) {
131
                                        highIndex = mIndx - 1;
132
                                }
133
                                else {
134
                                        lowIndex = mIndx + 1;
135
                                }
136
                        }
137
                        
138
                        currentIteration ++;
139
                }
140
                
141
                // If no item has been found -> return null
142
                return null;
143
        }
144
        
145
        /**
146
         * This method should be used when is wanted not to distinguish small letters from capital letters during the search.
147
         *   
148
         * It's necessary that all items of the array implement the {@link Comparable} interface.<br>
149
         * And it's also necessary that the value returned by the <i>toString()</i> method of each item (supposing 
150
         *   they inherit from Object) would be the expected value user saw (that would be used to compare the items).
151
         *
152
         * In this particular situation, it's supposed that the vector is sort ordered according the default algorithm of Java; this has the problem that
153
         *   it doesn't consideres the special characters and the orthographic rules of languages that aren't English, and then, for a particular
154
         *   <i>text</i> search, an incorrect result could be obtained. The solution decided for this problem has been to modify the algorithm, for seach
155
         *   into two ranks.
156
         *
157
         * @param text java.lang.String
158
         * @param sortOrderedItems java.util.Vector
159
         */
160
        public synchronized static List doSearchIgnoringCaseSensitive(String text, Vector sortOrderedItems) {
161
                int currentIteration = 0;
162
                int size = sortOrderedItems.size();
163
                int maxNumberOfIterations = (int) MathExtensionReduced.log2(size);
164
                int lowIndex = 0;
165
                int highIndex = sortOrderedItems.size() - 1;
166
                int mIndx;
167
                List list = null;
168
                List list2 = null;
169

    
170
                // FIRST RANK
171
                while ((lowIndex <= highIndex) && (currentIteration <= maxNumberOfIterations)) {
172
                        mIndx = ( lowIndex + highIndex ) / 2;
173
                        
174
                        if ( sortOrderedItems.get( mIndx ).toString().toLowerCase().startsWith( text.toLowerCase() ) ) {
175
                                lowIndex = highIndex = mIndx;
176
                                highIndex ++;
177
                                
178
                                // Expand the rank to up
179
                                while ( ( highIndex < size ) && ( sortOrderedItems.get( highIndex ).toString().toLowerCase().startsWith( text.toLowerCase() ) ) ) {
180
                                        highIndex ++;
181
                                }
182

    
183
                                // Expand the rank to down
184
                                while ( ( (lowIndex - 1) > -1 ) && ( sortOrderedItems.get( (lowIndex - 1) ).toString().toLowerCase().startsWith( text.toLowerCase() ) ) ) {
185
                                        lowIndex --;
186
                                }
187
                                
188
                                // Returns all items in the rank
189
                                list = Arrays.asList((sortOrderedItems.subList(lowIndex, highIndex)).toArray());
190
                                break;
191
                        }
192
                        else {
193
                                if ( sortOrderedItems.get( mIndx ).toString().compareTo( text ) > 0 ) {
194
                                        highIndex = mIndx - 1;
195
                                }
196
                                else {
197
                                        lowIndex = mIndx + 1;
198
                                }
199
                        }
200
                        
201
                        currentIteration ++;
202
                }
203

    
204
                // SECOND RANK
205
                currentIteration = 0;
206
                lowIndex = 0;
207
                highIndex = sortOrderedItems.size() - 1;
208

    
209
                while ((lowIndex <= highIndex) && (currentIteration <= maxNumberOfIterations)) {
210
                        mIndx = ( lowIndex + highIndex ) / 2;
211
                        
212
                        if ( sortOrderedItems.get( mIndx ).toString().toLowerCase().startsWith( text.toLowerCase() ) ) {
213
                                lowIndex = highIndex = mIndx;
214
                                highIndex ++;
215
                                
216
                                // Expand the rank to up
217
                                while ( ( highIndex < size ) && ( sortOrderedItems.get( highIndex ).toString().toLowerCase().startsWith( text.toLowerCase() ) ) ) {
218
                                        highIndex ++;
219
                                }
220

    
221
                                // Expand the rank to down
222
                                while ( ( (lowIndex - 1) > -1 ) && ( sortOrderedItems.get( (lowIndex - 1) ).toString().toLowerCase().startsWith( text.toLowerCase() ) ) ) {
223
                                        lowIndex --;
224
                                }
225
                                
226
                                // Returns all items in the rank                        
227
                                list2 = Arrays.asList((sortOrderedItems.subList(lowIndex, highIndex)).toArray()); // Breaks the loop
228
                                
229
                                if (list == null)
230
                                        return list2;
231
                                else {
232
                                        if (list2 == null)
233
                                                return null;
234

    
235
                                        Object obj;
236
                                        int j;
237
                                        
238
                                        list = new ArrayList(list.subList(0, list.size()));
239
                                        
240
                                        for (int i = 0; i < list2.size(); i ++) {
241
                                                obj = list2.get(i);
242
                                        
243
                                                // Don't add items which are already in the list
244
                                                if (!list.contains(obj)) {                
245
                                                        // Adds in sort order the new item:
246
                                                        for (j = 0; j < list.size(); j ++) {
247
                                                                if (list.get(j).toString().compareTo(obj.toString()) > 0)
248
                                                                        break;
249
                                                        }
250
                                                        
251
                                                        list.add(j, obj);
252
                                                }
253
                                        }
254
                                        
255
                                        // It's possible that some elements at the end wouldn't be found -> another small search
256
                                        size = list.size();
257
                                        if (size == 0) {
258
                                                j = 0;
259
                                        }
260
                                        else {
261
                                                j = sortOrderedItems.indexOf(list.get(size - 1));
262
                                        }
263
                                        
264
                                        j++;
265
                                        
266
                                        if (j < sortOrderedItems.size()) {
267
                                                do {
268
                                                        obj = sortOrderedItems.get( j );
269
                                                        
270
                                                        if (obj.toString().toLowerCase().startsWith( text.toLowerCase())) {
271
                                                                list.add(size, obj);
272
                                                        }
273
                                                        
274
                                                        j++;
275
                                                }
276
                                                while (j < sortOrderedItems.size());
277
                                        }
278
                                        
279
                                        return list;
280
                                }
281
                        }
282
                        else {
283
                                if ( sortOrderedItems.get( mIndx ).toString().toLowerCase().compareTo( text.toLowerCase() ) > 0 ) {
284
                                        highIndex = mIndx - 1;
285
                                }
286
                                else {
287
                                        lowIndex = mIndx + 1;
288
                                }
289
                        }
290
                        
291
                        currentIteration ++;
292
                }
293
                
294
                return null;
295
        }
296
        
297
//        /** THIS VERSION FAILURES IN SOME PARTICULAR SITUATIONS
298
//         * This method should be used when is wanted distinguish small letters from capital letters during the search, and the comparation of items
299
//         *   done according an algorithm we define.
300
//         *   
301
//         * And it's also necessary that the value returned by the <i>toString()</i> method of each item (supposing 
302
//         *   they inherit from Object) would be the expected value user saw (that would be used to compare the items).
303
//         *   
304
//         * @param text java.lang.String
305
//         * @param sortOrderedItems java.util.Vector
306
//         * @param comp An Comparator object which implements the <i><b>compareTo()</b><i>  method.
307
//         */
308
//        public synchronized static List doSearchConsideringCaseSensitive(String text, Vector sortOrderedItems, Comparator comp) {
309
//                int currentIteration = 0;
310
//                int size = sortOrderedItems.size();
311
//                int maxNumberOfIterations = (int) MathExtension.log2(size);
312
//                int lowIndex = 0;
313
//                int highIndex = sortOrderedItems.size() - 1;
314
//                int mIndx;
315
//
316
//
317
//                while ((lowIndex <= highIndex) && (currentIteration <= maxNumberOfIterations)) {
318
//                        mIndx = ( lowIndex + highIndex ) / 2;
319
//
320
//                        if ( sortOrderedItems.get( mIndx ).toString().startsWith( text ) ) {
321
//                                lowIndex = highIndex = mIndx;
322
//                                highIndex ++;
323
//
324
//                                // Expand the rank to up
325
//                                while ( ( highIndex < size ) && ( sortOrderedItems.get( highIndex ).toString().startsWith( text ) ) ) {
326
//                                        highIndex ++;
327
//                                }
328
//
329
//                                // Expand the rank to down
330
//                                while ( ( (lowIndex - 1) > -1 ) && ( sortOrderedItems.get( (lowIndex - 1) ).toString().startsWith( text ) ) ) {
331
//                                        lowIndex --;
332
//                                }
333
//
334
//                                // It's possible that items with different case, should be between the same case, then this item will be added individually:
335
//                                List list = new Vector(sortOrderedItems.subList(lowIndex, highIndex));
336
//                                
337
//
338
//                                // Expand to down
339
//                                lowIndex --;
340
//                                while ( ( lowIndex > -1 ) && ( sortOrderedItems.get( (lowIndex ) ).toString().toLowerCase().startsWith( text.toLowerCase() ) ) ) {
341
//                                        if (sortOrderedItems.get( lowIndex ).toString().startsWith( text )) {
342
//                                                list.add(0, sortOrderedItems.get( lowIndex ));
343
//                                        }
344
//                                        
345
//                                        lowIndex --;
346
//                                }
347
//                                
348
//                                // Expand to up
349
//                                while ( ( highIndex < size ) && ( sortOrderedItems.get( highIndex ).toString().toLowerCase().startsWith( text.toLowerCase() ) ) ) {
350
//                                        if (sortOrderedItems.get( highIndex ).toString().startsWith( text )) {                                                
351
//                                                list.add(list.size(), sortOrderedItems.get( highIndex ));
352
//                                        }
353
//                                        
354
//                                        highIndex ++;
355
//                                }
356
//                                
357
//                                // Returns all items in the rank
358
//                                return list; // Breaks the loop
359
//                        }
360
//                        else {
361
//                                if ( comp.compare(sortOrderedItems.get( mIndx ), text ) > 0 ) {
362
//                                        highIndex = mIndx - 1;
363
//                                }
364
//                                else {
365
//                                        lowIndex = mIndx + 1;
366
//                                }
367
//                        }
368
//
369
//                        currentIteration ++;
370
//                }
371
//
372
//                // If no item has been found -> return null
373
//                return null;
374
//        }
375
        
376
        /**
377
         * This method should be used when is wanted distinguish small letters from capital letters during the search, and the comparation of items
378
         *   done according an algorithm we define.
379
         *   
380
         * And it's also necessary that the value returned by the <i>toString()</i> method of each item (supposing 
381
         *   they inherit from Object) would be the expected value user saw (that would be used to compare the items).
382
         *   
383
         * @param text java.lang.String
384
         * @param sortOrderedItems java.util.Vector
385
         * @param comp An Comparator object which implements the <i><b>compareTo()</b><i>  method.
386
         */
387
        public synchronized static List doSearchConsideringCaseSensitive(String text, Vector sortOrderedItems, Comparator comp) {
388
                List results_list = doSearchIgnoringCaseSensitive(text, sortOrderedItems, comp);
389

    
390
                if (results_list == null)
391
                        return null;
392

    
393
                List results = new ArrayList();
394

    
395
                for (int i = 0; i < (results_list.size()); i++) {
396
                        if (results_list.get(i).toString().startsWith(text)) {
397
                                results.add(results_list.get(i));
398
                        }
399
                }
400

    
401
                return results;
402
        }
403
        
404
        /**
405
         * This method should be used when is wanted not to distinguish small letters from capital letters during the search, and the comparation of items
406
         *   done according an algorithm we define.
407
         *   
408
         * And it's also necessary that the value returned by the <i>toString()</i> method of each item (supposing 
409
         *   they inherit from Object) would be the expected value user saw (that would be used to compare the items).
410
         *
411
         * @param text java.lang.String
412
         * @param sortOrderedItems java.util.Vector
413
         * @param comp An Comparator object which implements the <i><b>compareTo()</b><i>  method.
414
         */
415
        public synchronized static List doSearchIgnoringCaseSensitive(String text, Vector sortOrderedItems, Comparator comp) {
416
                int currentIteration = 0;
417
                int size = sortOrderedItems.size();
418
                int maxNumberOfIterations = (int) MathExtensionReduced.log2(size);
419
                int lowIndex = 0;
420
                int highIndex = sortOrderedItems.size() - 1;
421
                int mIndx;
422
                
423
                while ((lowIndex <= highIndex) && (currentIteration <= maxNumberOfIterations)) {
424
                        mIndx = ( lowIndex + highIndex ) / 2;
425

    
426
                        if ( sortOrderedItems.get( mIndx ).toString().toLowerCase().startsWith( text.toLowerCase() ) ) {
427
                                lowIndex = highIndex = mIndx;
428
                                highIndex ++;
429
                                
430
                                // Expand the rank to up
431
                                while ( ( highIndex < size ) && ( sortOrderedItems.get( highIndex ).toString().toLowerCase().startsWith( text.toLowerCase() ) ) ) {
432
                                        highIndex ++;
433
                                }
434

    
435
                                // Expand the rank to down
436
                                while ( ( (lowIndex - 1) > -1 ) && ( sortOrderedItems.get( (lowIndex - 1) ).toString().toLowerCase().startsWith( text.toLowerCase() ) ) ) {
437
                                        lowIndex --;
438
                                }
439
                                
440
                                // Returns all items in the rank                        
441
                                return Arrays.asList((sortOrderedItems.subList(lowIndex, highIndex)).toArray()); // Breaks the loop
442
                        }
443
                        else {
444
                                if ( comp.compare(sortOrderedItems.get( mIndx ).toString().toLowerCase(), text.toLowerCase() ) > 0 ) {
445
                                        highIndex = mIndx - 1;
446
                                }
447
                                else {
448
                                        lowIndex = mIndx + 1;
449
                                }
450
                        }
451
                        
452
                        currentIteration ++;
453
                }
454
                
455
                return null;
456
        }
457
}