This Bugzilla instance is a read-only archive of historic NetBeans bug reports. To report a bug in NetBeans please follow the project's instructions for reporting issues.

View | Details | Raw Unified | Return to bug 185168
Collapse All | Expand All

(-)a/cnd.gotodeclaration/nbproject/project.xml (-1 / +1 lines)
Lines 55-61 Link Here
55
                    <compile-dependency/>
55
                    <compile-dependency/>
56
                    <run-dependency>
56
                    <run-dependency>
57
                        <release-version>1</release-version>
57
                        <release-version>1</release-version>
58
                        <specification-version>1.2</specification-version>
58
                        <specification-version>1.17</specification-version>
59
                    </run-dependency>
59
                    </run-dependency>
60
                </dependency>
60
                </dependency>
61
                <dependency>
61
                <dependency>
(-)a/cnd.gotodeclaration/src/org/netbeans/modules/cnd/gotodeclaration/matcher/NameMatcherFactory.java (-135 / +2 lines)
Lines 27-35 Link Here
27
 */
27
 */
28
package org.netbeans.modules.cnd.gotodeclaration.matcher;
28
package org.netbeans.modules.cnd.gotodeclaration.matcher;
29
29
30
import java.util.regex.Pattern;
31
import java.util.regex.PatternSyntaxException;
32
import org.netbeans.modules.cnd.api.model.services.CsmSelect;
30
import org.netbeans.modules.cnd.api.model.services.CsmSelect;
31
import org.netbeans.spi.jumpto.support.NameMatcher;
33
import org.netbeans.spi.jumpto.type.SearchType;
32
import org.netbeans.spi.jumpto.type.SearchType;
34
33
35
/**
34
/**
Lines 39-179 Link Here
39
 * @author Vladimir Kvashin
38
 * @author Vladimir Kvashin
40
 */
39
 */
41
public class NameMatcherFactory {
40
public class NameMatcherFactory {
42
43
    private NameMatcherFactory() {
44
    }
45
    
46
    private static abstract class BaseNameMatcher implements NameMatcher {
47
	
48
        protected String patternText;
49
	
50
	protected BaseNameMatcher(String patternText) {
51
	    this.patternText = patternText;
52
	}
53
    }
54
    
55
    
56
    private static final class ExactNameMatcher extends BaseNameMatcher implements NameMatcher {
57
	
58
	public ExactNameMatcher(String patternText) {
59
	    super(patternText);
60
	}
61
62
        @Override
63
	public final boolean accept(String name) {
64
	    return patternText.equals(name);
65
	}
66
    }
67
68
    private static final class CaseInsensitiveExactNameMatcher extends BaseNameMatcher implements NameMatcher {
69
	
70
	public CaseInsensitiveExactNameMatcher(String patternText) {
71
	    super(patternText);
72
	}
73
74
        @Override
75
	public final boolean accept(String name) {
76
	    return patternText.equalsIgnoreCase(name);
77
	}
78
    }
79
80
    private static final class PrefixNameMatcher extends BaseNameMatcher implements NameMatcher {
81
	
82
	public PrefixNameMatcher(String patternText) {
83
	    super(patternText);
84
	}
85
	
86
        @Override
87
	public final boolean accept(String name) {
88
	    return name != null && name.startsWith(patternText);
89
	}
90
    }
91
92
    private static final class CaseInsensitivePrefixNameMatcher extends BaseNameMatcher implements NameMatcher {
93
	
94
	public CaseInsensitivePrefixNameMatcher(String patternText) {
95
	    super(patternText.toLowerCase());
96
	}
97
	
98
        @Override
99
	public final boolean accept(String name) {
100
	    return name != null && name.toLowerCase().startsWith(patternText);
101
	}
102
    }
103
104
    private static final class RegExpNameMatcher implements NameMatcher {
105
106
	Pattern pattern;
107
	
108
	public RegExpNameMatcher(String patternText, boolean caseSensitive) {
109
	    pattern = Pattern.compile(patternText, caseSensitive ? 0 : Pattern.CASE_INSENSITIVE);
110
	}
111
	
112
        @Override
113
	public final boolean accept(String name) {
114
	    return name != null && pattern.matcher(name).matches();
115
	}
116
    }
117
118
    private static final class CamelCaseNameMatcher implements NameMatcher {
119
120
	Pattern pattern;
121
	
122
	public CamelCaseNameMatcher(String name) {
123
            if (name.length() == 0) {
124
                throw new IllegalArgumentException ();
125
            }        
126
            final StringBuilder patternString = new StringBuilder ();                        
127
            for (int i=0; i<name.length(); i++) {
128
                char c = name.charAt(i);
129
                patternString.append(c);
130
                if (i == name.length()-1) {
131
                    patternString.append("\\w*");  // NOI18N
132
                }
133
                else {
134
                    patternString.append("[\\p{Lower}\\p{Digit}]*");  // NOI18N
135
                }
136
            }
137
            pattern = Pattern.compile(patternString.toString());
138
	}
139
	
140
        @Override
141
	public final boolean accept(String name) {
142
	    return name != null && pattern.matcher(name).matches();
143
	}
144
    }
145
146
    /**
147
     * Get a name
148
     */
149
    public static NameMatcher createNameMatcher(String text, SearchType type) {
150
        try {
151
            switch( type ) {
152
                case EXACT_NAME:
153
                    return new ExactNameMatcher(text);
154
                case CASE_INSENSITIVE_EXACT_NAME:
155
                    return new CaseInsensitiveExactNameMatcher(text);
156
                case PREFIX:
157
                    return new PrefixNameMatcher(text);
158
                case REGEXP:
159
                    return new RegExpNameMatcher(text, true);
160
                case CASE_INSENSITIVE_REGEXP:
161
                    return new RegExpNameMatcher(text, false);
162
                case CASE_INSENSITIVE_PREFIX:
163
                     return new CaseInsensitivePrefixNameMatcher(text);
164
                case CAMEL_CASE:
165
                    return new CamelCaseNameMatcher(text);
166
                default:
167
                    return null;
168
            }
169
        }
170
        catch( PatternSyntaxException ex ) {
171
            return null;
172
        }
173
    }    
174
    
41
    
175
    public static CsmSelect.CsmFilter createNameFilter(String text, SearchType type) {
42
    public static CsmSelect.CsmFilter createNameFilter(String text, SearchType type) {
176
        final NameMatcher matcher = createNameMatcher(text, type);
43
        final NameMatcher matcher = org.netbeans.spi.jumpto.support.NameMatcherFactory.createNameMatcher(text, type);
177
        if( matcher != null ) {
44
        if( matcher != null ) {
178
            CsmSelect.NameAcceptor acceptor = new CsmSelect.NameAcceptor() {
45
            CsmSelect.NameAcceptor acceptor = new CsmSelect.NameAcceptor() {
179
                @Override
46
                @Override
(-)a/cnd.gotodeclaration/src/org/netbeans/modules/cnd/gotodeclaration/symbol/CppSymbolProvider.java (-11 / +7 lines)
Lines 67-75 Link Here
67
import org.netbeans.modules.cnd.api.model.services.CsmSelect.NameAcceptor;
67
import org.netbeans.modules.cnd.api.model.services.CsmSelect.NameAcceptor;
68
import org.netbeans.modules.cnd.api.model.util.CsmKindUtilities;
68
import org.netbeans.modules.cnd.api.model.util.CsmKindUtilities;
69
import org.netbeans.modules.cnd.api.project.NativeProject;
69
import org.netbeans.modules.cnd.api.project.NativeProject;
70
import org.netbeans.modules.cnd.gotodeclaration.matcher.NameMatcher;
71
import org.netbeans.modules.cnd.gotodeclaration.matcher.NameMatcherFactory;
72
import org.netbeans.modules.cnd.utils.CndUtils;
70
import org.netbeans.modules.cnd.utils.CndUtils;
71
import org.netbeans.spi.jumpto.support.NameMatcher;
72
import org.netbeans.spi.jumpto.support.NameMatcherFactory;
73
import org.netbeans.spi.jumpto.symbol.SymbolProvider;
73
import org.netbeans.spi.jumpto.symbol.SymbolProvider;
74
import org.netbeans.spi.jumpto.type.SearchType;
74
import org.netbeans.spi.jumpto.type.SearchType;
75
import org.openide.util.NbBundle;
75
import org.openide.util.NbBundle;
Lines 115-129 Link Here
115
115
116
    private CsmSelect.NameAcceptor createNameAcceptor(final Context context) {
116
    private CsmSelect.NameAcceptor createNameAcceptor(final Context context) {
117
        final NameMatcher nameMatcher = NameMatcherFactory.createNameMatcher(context.getText(), context.getSearchType());
117
        final NameMatcher nameMatcher = NameMatcherFactory.createNameMatcher(context.getText(), context.getSearchType());
118
        if (nameMatcher == null) {
118
        return new CsmSelect.NameAcceptor() {
119
            return null;
119
            public boolean accept(CharSequence name) {
120
        } else {
120
                return nameMatcher.accept(name.toString());
121
            return new CsmSelect.NameAcceptor() {
121
            }
122
                public boolean accept(CharSequence name) {
122
        };
123
                    return nameMatcher.accept(name.toString());
124
                }
125
            };
126
        }
127
    }
123
    }
128
124
129
    // synchronized is just in case here - it shouldn't be called async
125
    // synchronized is just in case here - it shouldn't be called async
(-)a/cnd.gotodeclaration/src/org/netbeans/modules/cnd/gotodeclaration/type/CppTypeProvider.java (-4 / +4 lines)
Lines 32-39 Link Here
32
32
33
import org.netbeans.api.project.Project;
33
import org.netbeans.api.project.Project;
34
import org.netbeans.modules.cnd.api.model.services.CsmSelect;
34
import org.netbeans.modules.cnd.api.model.services.CsmSelect;
35
import org.netbeans.modules.cnd.gotodeclaration.matcher.NameMatcher;
35
import org.netbeans.spi.jumpto.support.NameMatcher;
36
import org.netbeans.modules.cnd.gotodeclaration.matcher.NameMatcherFactory;
36
import org.netbeans.spi.jumpto.support.NameMatcherFactory;
37
37
38
import org.netbeans.spi.jumpto.type.SearchType;
38
import org.netbeans.spi.jumpto.type.SearchType;
39
import org.netbeans.spi.jumpto.type.TypeDescriptor;
39
import org.netbeans.spi.jumpto.type.TypeDescriptor;
Lines 77-85 Link Here
77
	
77
	
78
	
78
	
79
	
79
	
80
	CsmSelect.CsmFilter filter = NameMatcherFactory.createNameFilter(text, type);
80
	CsmSelect.CsmFilter filter = org.netbeans.modules.cnd.gotodeclaration.matcher.NameMatcherFactory.createNameFilter(text, type);
81
	NameMatcher matcher = NameMatcherFactory.createNameMatcher(text, type);
81
	NameMatcher matcher = NameMatcherFactory.createNameMatcher(text, type);
82
	if( filter == null || matcher == null) {
82
	if( filter == null) {
83
	    return;
83
	    return;
84
	}
84
	}
85
        
85
        
(-)a/jumpto/apichanges.xml (+16 lines)
Lines 105-110 Link Here
105
    <!-- ACTUAL CHANGES BEGIN HERE: -->
105
    <!-- ACTUAL CHANGES BEGIN HERE: -->
106
106
107
    <changes>
107
    <changes>
108
        <change id="Support">
109
            <api name="general"/>
110
            <summary>Added support SPI to implement name filters</summary>
111
            <version major="1" minor="17"/>
112
            <date day="5" month="5" year="2010"/>
113
            <author login="tzezula"/>
114
            <compatibility addition="yes">
115
            </compatibility>
116
            <description>
117
                Added support SPI to implement common filters used by Go To Type, Go To Symbol,
118
                Go To File.
119
            </description>
120
            <class package="org.netbeans.spi.jumpto.support" name="NameMatcherFactory"/>
121
            <class package="org.netbeans.spi.jumpto.support" name="NameMatcher"/>
122
            <issue number="185168"/>
123
        </change>
108
        <change id="GoToFile">
124
        <change id="GoToFile">
109
            <api name="general"/>
125
            <api name="general"/>
110
            <summary>Added SPI for Go to File dialog</summary>
126
            <summary>Added SPI for Go to File dialog</summary>
(-)a/jumpto/manifest.mf (-1 / +1 lines)
Lines 2-6 Link Here
2
OpenIDE-Module: org.netbeans.modules.jumpto/1
2
OpenIDE-Module: org.netbeans.modules.jumpto/1
3
OpenIDE-Module-Layer: org/netbeans/modules/jumpto/resources/layer.xml
3
OpenIDE-Module-Layer: org/netbeans/modules/jumpto/resources/layer.xml
4
OpenIDE-Module-Localizing-Bundle: org/netbeans/modules/jumpto/resources/Bundle.properties
4
OpenIDE-Module-Localizing-Bundle: org/netbeans/modules/jumpto/resources/Bundle.properties
5
OpenIDE-Module-Specification-Version: 1.16
5
OpenIDE-Module-Specification-Version: 1.17
6
AutoUpdate-Show-In-Client: false
6
AutoUpdate-Show-In-Client: false
(-)a/jumpto/nbproject/project.xml (+1 lines)
Lines 225-230 Link Here
225
                <package>org.netbeans.spi.jumpto.file</package>
225
                <package>org.netbeans.spi.jumpto.file</package>
226
                <package>org.netbeans.spi.jumpto.symbol</package>
226
                <package>org.netbeans.spi.jumpto.symbol</package>
227
                <package>org.netbeans.spi.jumpto.type</package>
227
                <package>org.netbeans.spi.jumpto.type</package>
228
                <package>org.netbeans.spi.jumpto.support</package>
228
            </friend-packages>
229
            </friend-packages>
229
        </data>
230
        </data>
230
    </configuration>
231
    </configuration>
(-)a/jumpto/src/org/netbeans/modules/jumpto/file/FileSearchAction.java (-132 / +6 lines)
Lines 68-75 Link Here
68
import java.util.Set;
68
import java.util.Set;
69
import java.util.logging.Level;
69
import java.util.logging.Level;
70
import java.util.logging.Logger;
70
import java.util.logging.Logger;
71
import java.util.regex.Matcher;
72
import java.util.regex.Pattern;
73
import java.util.regex.PatternSyntaxException;
71
import java.util.regex.PatternSyntaxException;
74
import javax.swing.AbstractAction;
72
import javax.swing.AbstractAction;
75
import javax.swing.DefaultListCellRenderer;
73
import javax.swing.DefaultListCellRenderer;
Lines 100-105 Link Here
100
import org.netbeans.spi.jumpto.file.FileDescriptor;
98
import org.netbeans.spi.jumpto.file.FileDescriptor;
101
import org.netbeans.spi.jumpto.file.FileProvider;
99
import org.netbeans.spi.jumpto.file.FileProvider;
102
import org.netbeans.spi.jumpto.file.FileProviderFactory;
100
import org.netbeans.spi.jumpto.file.FileProviderFactory;
101
import org.netbeans.spi.jumpto.support.NameMatcher;
102
import org.netbeans.spi.jumpto.support.NameMatcherFactory;
103
import org.netbeans.spi.jumpto.type.SearchType;
103
import org.netbeans.spi.jumpto.type.SearchType;
104
import org.openide.DialogDescriptor;
104
import org.openide.DialogDescriptor;
105
import org.openide.DialogDisplayer;
105
import org.openide.DialogDisplayer;
Lines 467-473 Link Here
467
                    }
467
                    }
468
                }
468
                }
469
                //Ask GTF providers
469
                //Ask GTF providers
470
                final FileProvider.Context ctx = FileProviderAccessor.getInstance().createContext(text, toJumpToSearchType(searchType), currentProject);
470
                final SearchType jumpToSearchType = toJumpToSearchType(searchType);
471
                final FileProvider.Context ctx = FileProviderAccessor.getInstance().createContext(text, jumpToSearchType, currentProject);
471
                final FileProvider.Result fpR = FileProviderAccessor.getInstance().createResult(files,new String[1], ctx);
472
                final FileProvider.Result fpR = FileProviderAccessor.getInstance().createResult(files,new String[1], ctx);
472
                for (FileProvider provider : getProviders()) {
473
                for (FileProvider provider : getProviders()) {
473
                    currentProvider = provider;
474
                    currentProvider = provider;
Lines 497-502 Link Here
497
                    allFolders = searchSources(root, allFolders, excludes, filters);
498
                    allFolders = searchSources(root, allFolders, excludes, filters);
498
                }
499
                }
499
                //Looking for matching files in all found folders
500
                //Looking for matching files in all found folders
501
                final NameMatcher matcher = NameMatcherFactory.createNameMatcher(text, jumpToSearchType);
500
                for (FileObject folder: allFolders) {
502
                for (FileObject folder: allFolders) {
501
                    assert folder.isFolder();
503
                    assert folder.isFolder();
502
                    Enumeration<? extends FileObject> filesInFolder = folder.getData(false);
504
                    Enumeration<? extends FileObject> filesInFolder = folder.getData(false);
Lines 504-510 Link Here
504
                        FileObject file = filesInFolder.nextElement();
506
                        FileObject file = filesInFolder.nextElement();
505
                        if (file.isFolder()) continue;
507
                        if (file.isFolder()) continue;
506
508
507
                        if (isMatchedFileObject(searchType, file, text)) {
509
                        if (matcher.accept(file.getNameExt())) {
508
                            Project project = FileOwnerQuery.getOwner(file);
510
                            Project project = FileOwnerQuery.getOwner(file);
509
                            boolean preferred = project != null && currentProject != null ? project.getProjectDirectory() == currentProject.getProjectDirectory() : false;
511
                            boolean preferred = project != null && currentProject != null ? project.getProjectDirectory() == currentProject.getProjectDirectory() : false;
510
                            String relativePath = FileUtil.getRelativePath(project.getProjectDirectory(), file);
512
                            String relativePath = FileUtil.getRelativePath(project.getProjectDirectory(), file);
Lines 564-697 Link Here
564
//            }
566
//            }
565
        }
567
        }
566
        return result;
568
        return result;
567
    }
568
569
    private boolean isMatchedFileObject(QuerySupport.Kind searchType, FileObject file, String text) {
570
        boolean isMatched = false;
571
        switch (searchType) {
572
            case EXACT: {
573
                isMatched = file.getNameExt().equals(text);
574
                break;
575
            }
576
            case PREFIX: {
577
                if (text.length() == 0) {
578
                    isMatched = true;
579
                } else {
580
                    isMatched = file.getNameExt().startsWith(text);
581
                }
582
                break;
583
            }
584
            case CASE_INSENSITIVE_PREFIX: {
585
                if (text.length() == 0) {
586
                    isMatched = true;
587
                } else {
588
                    isMatched = file.getNameExt().toLowerCase().startsWith(text.toLowerCase());
589
                }
590
                break;
591
            }
592
            case CAMEL_CASE: {
593
                if (text.length() == 0) {
594
                    throw new IllegalArgumentException ();
595
                }
596
                {
597
                    StringBuilder sb = new StringBuilder();
598
                    String prefix = null;
599
                    int lastIndex = 0;
600
                    int index;
601
                    do {
602
                        index = findNextUpper(text, lastIndex + 1);
603
                        String token = text.substring(lastIndex, index == -1 ? text.length(): index);
604
                        if ( lastIndex == 0 ) {
605
                            prefix = token;
606
                        }
607
                        sb.append(token);
608
                        sb.append( index != -1 ?  "[\\p{javaLowerCase}\\p{Digit}_\\$]*" : ".*"); // NOI18N
609
                        lastIndex = index;
610
                    }
611
                    while(index != -1);
612
613
                    final Pattern pattern = Pattern.compile(sb.toString());
614
                    Matcher m = pattern.matcher(file.getNameExt());
615
                    isMatched = m.matches();
616
                }
617
                break;
618
619
            }
620
621
            case CASE_INSENSITIVE_REGEXP:
622
                if (text.length() == 0) {
623
                    throw new IllegalArgumentException ();
624
                } else {
625
                    if (Character.isJavaIdentifierStart(text.charAt(0))) {
626
                        Pattern pattern = Pattern.compile(text,Pattern.CASE_INSENSITIVE);
627
                        Matcher m = pattern.matcher(file.getNameExt());
628
                        isMatched = m.matches();
629
                    }
630
                    else {
631
                        Pattern pattern = Pattern.compile(text,Pattern.CASE_INSENSITIVE|Pattern.DOTALL);
632
                        Matcher m = pattern.matcher(file.getNameExt());
633
                        isMatched = m.matches();
634
                    }
635
                    break;
636
                }
637
            case REGEXP:
638
                if (text.length() == 0) {
639
                    throw new IllegalArgumentException ();
640
                } else {
641
                    if (Character.isJavaIdentifierStart(text.charAt(0))) {
642
                        final Pattern pattern = Pattern.compile(text);
643
                        Matcher m = pattern.matcher(file.getNameExt());
644
                        isMatched = m.matches();
645
                    }
646
                    else {
647
                        final Pattern pattern = Pattern.compile(text,Pattern.DOTALL);
648
                        Matcher m = pattern.matcher(file.getNameExt());
649
                        isMatched = m.matches();
650
                    }
651
                    break;
652
                }
653
654
            case CASE_INSENSITIVE_CAMEL_CASE: {
655
                if (text.length() == 0) {
656
                    throw new IllegalArgumentException ();
657
                }
658
                {
659
                    StringBuilder sb = new StringBuilder();
660
                    String prefix = null;
661
                    int lastIndex = 0;
662
                    int index;
663
                    do {
664
                        index = findNextUpper(text, lastIndex + 1);
665
                        String token = text.substring(lastIndex, index == -1 ? text.length(): index);
666
                        if ( lastIndex == 0 ) {
667
                            prefix = token;
668
                        }
669
                        sb.append(token);
670
                        sb.append( index != -1 ?  "[\\p{javaLowerCase}\\p{Digit}_\\$]*" : ".*"); // NOI18N
671
                        lastIndex = index;
672
                    }
673
                    while(index != -1);
674
675
                    final Pattern pattern = Pattern.compile(sb.toString(),Pattern.CASE_INSENSITIVE);
676
                    Matcher m = pattern.matcher(file.getNameExt());
677
                    isMatched = m.matches();
678
                }
679
                break;
680
            }
681
            default:
682
                throw new UnsupportedOperationException (searchType.toString());
683
684
        }
685
        return isMatched;
686
    }//checkMatch
687
    private static int findNextUpper(String text, int offset ) {
688
689
        for( int i = offset; i < text.length(); i++ ) {
690
            if ( Character.isUpperCase(text.charAt(i)) ) {
691
                return i;
692
            }
693
        }
694
        return -1;
695
    }
569
    }
696
570
697
    private boolean checkAgainstFilters(FileObject folder, FileObjectFilter[] filters) {
571
    private boolean checkAgainstFilters(FileObject folder, FileObjectFilter[] filters) {
(-)a/jumpto/src/org/netbeans/spi/jumpto/support/NameMatcher.java (+42 lines)
Line 0 Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
5
 *
6
 * The contents of this file are subject to the terms of either the GNU
7
 * General Public License Version 2 only ("GPL") or the Common
8
 * Development and Distribution License("CDDL") (collectively, the
9
 * "License"). You may not use this file except in compliance with the
10
 * License. You can obtain a copy of the License at
11
 * http://www.netbeans.org/cddl-gplv2.html
12
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
13
 * specific language governing permissions and limitations under the
14
 * License.  When distributing the software, include this License Header
15
 * Notice in each file and include the License file at
16
 * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
17
 * particular file as subject to the "Classpath" exception as provided
18
 * by Sun in the GPL Version 2 section of the License file that
19
 * accompanied this code. If applicable, add the following below the
20
 * License Header, with the fields enclosed by brackets [] replaced by
21
 * your own identifying information:
22
 * "Portions Copyrighted [year] [name of copyright owner]"
23
 *
24
 * Contributor(s):
25
 *
26
 * Portions Copyrighted 2007 Sun Microsystems, Inc.
27
 */
28
29
package org.netbeans.spi.jumpto.support;
30
31
/**
32
 * Used for encapsulation of the  different matching algorithms
33
 * (such as String.equals, String.equalsIgnoreCase, String.startWith, etc)
34
 */
35
public interface NameMatcher {
36
37
    /**
38
     * Determine whether the name matches a pattern or not
39
     * return true
40
     */
41
    boolean accept(String name);
42
}
(-)a/jumpto/src/org/netbeans/spi/jumpto/support/NameMatcherFactory.java (+180 lines)
Line 0 Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
5
 *
6
 * The contents of this file are subject to the terms of either the GNU
7
 * General Public License Version 2 only ("GPL") or the Common
8
 * Development and Distribution License("CDDL") (collectively, the
9
 * "License"). You may not use this file except in compliance with the
10
 * License. You can obtain a copy of the License at
11
 * http://www.netbeans.org/cddl-gplv2.html
12
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
13
 * specific language governing permissions and limitations under the
14
 * License.  When distributing the software, include this License Header
15
 * Notice in each file and include the License file at
16
 * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
17
 * particular file as subject to the "Classpath" exception as provided
18
 * by Sun in the GPL Version 2 section of the License file that
19
 * accompanied this code. If applicable, add the following below the
20
 * License Header, with the fields enclosed by brackets [] replaced by
21
 * your own identifying information:
22
 * "Portions Copyrighted [year] [name of copyright owner]"
23
 *
24
 * Contributor(s):
25
 *
26
 * Portions Copyrighted 2007 Sun Microsystems, Inc.
27
 */
28
package org.netbeans.spi.jumpto.support;
29
30
import java.util.regex.Pattern;
31
import java.util.regex.PatternSyntaxException;
32
import org.netbeans.spi.jumpto.type.SearchType;
33
import org.openide.util.Parameters;
34
35
/**
36
 * A factory that provides comparators
37
 * depending on SearchType
38
 *
39
 * @author Vladimir Kvashin
40
 */
41
public final class NameMatcherFactory {
42
43
    private NameMatcherFactory() {
44
    }
45
46
    private static abstract class BaseNameMatcher implements NameMatcher {
47
48
        protected final String patternText;
49
50
	protected BaseNameMatcher(String patternText) {
51
	    this.patternText = patternText;
52
	}
53
    }
54
55
    private static final class ExactNameMatcher extends BaseNameMatcher {
56
57
	public ExactNameMatcher(String patternText) {
58
	    super(patternText);
59
	}
60
61
        @Override
62
	public final boolean accept(String name) {
63
	    return patternText.equals(name);
64
	}
65
    }
66
67
    private static final class CaseInsensitiveExactNameMatcher extends BaseNameMatcher {
68
69
	public CaseInsensitiveExactNameMatcher(String patternText) {
70
	    super(patternText);
71
	}
72
73
        @Override
74
	public final boolean accept(String name) {
75
	    return patternText.equalsIgnoreCase(name);
76
	}
77
    }
78
79
    private static final class PrefixNameMatcher extends BaseNameMatcher {
80
81
	public PrefixNameMatcher(String patternText) {
82
	    super(patternText);
83
	}
84
85
        @Override
86
	public final boolean accept(String name) {
87
	    return name != null && name.startsWith(patternText);
88
	}
89
    }
90
91
    private static final class CaseInsensitivePrefixNameMatcher extends BaseNameMatcher {
92
93
	public CaseInsensitivePrefixNameMatcher(String patternText) {
94
	    super(patternText.toLowerCase());
95
	}
96
97
        @Override
98
	public final boolean accept(String name) {
99
	    return name != null && name.toLowerCase().startsWith(patternText);
100
	}
101
    }
102
103
    private static final class RegExpNameMatcher implements NameMatcher {
104
105
	private final Pattern pattern;
106
107
	public RegExpNameMatcher(String patternText, boolean caseSensitive) {
108
	    pattern = Pattern.compile(patternText, caseSensitive ? 0 : Pattern.CASE_INSENSITIVE);
109
	}
110
111
        @Override
112
	public final boolean accept(String name) {
113
	    return name != null && pattern.matcher(name).matches();
114
	}
115
    }
116
117
    private static final class CamelCaseNameMatcher implements NameMatcher {
118
119
	private final Pattern pattern;
120
121
	public CamelCaseNameMatcher(String name) {
122
            if (name.length() == 0) {
123
                throw new IllegalArgumentException ();
124
            }
125
            final StringBuilder patternString = new StringBuilder ();
126
            for (int i=0; i<name.length(); i++) {
127
                char c = name.charAt(i);
128
                patternString.append(c);
129
                if (i == name.length()-1) {
130
                    patternString.append("\\w*");  // NOI18N
131
                }
132
                else {
133
                    patternString.append("[\\p{Lower}\\p{Digit}]*");  // NOI18N
134
                }
135
            }
136
            pattern = Pattern.compile(patternString.toString());
137
	}
138
139
        @Override
140
	public final boolean accept(String name) {
141
	    return name != null && pattern.matcher(name).matches();
142
	}
143
    }
144
145
    /**
146
     * Creates a {@link NameMatcher} of given type for text.
147
     * @param text to create {@link NameMatcher} for
148
     * @param type of {@link NameMatcher}
149
     * @return a {@link NameMatcher}
150
     * @throws IllegalArgumentException when called with unsupported type or
151
     * regular expression for given text failed.
152
     */
153
    public static NameMatcher createNameMatcher(String text, SearchType type) throws IllegalArgumentException {
154
        Parameters.notNull("text", text);   //NOI18N
155
        Parameters.notNull("type", type);   //NOI18N
156
        try {
157
            switch( type ) {
158
                case EXACT_NAME:
159
                    return new ExactNameMatcher(text);
160
                case CASE_INSENSITIVE_EXACT_NAME:
161
                    return new CaseInsensitiveExactNameMatcher(text);
162
                case PREFIX:
163
                    return new PrefixNameMatcher(text);
164
                case REGEXP:
165
                    return new RegExpNameMatcher(text, true);
166
                case CASE_INSENSITIVE_REGEXP:
167
                    return new RegExpNameMatcher(text, false);
168
                case CASE_INSENSITIVE_PREFIX:
169
                     return new CaseInsensitivePrefixNameMatcher(text);
170
                case CAMEL_CASE:
171
                    return new CamelCaseNameMatcher(text);
172
                default:
173
                    throw new IllegalArgumentException("Unsupported type: " + type);  //NOI18N
174
            }
175
        }
176
        catch( PatternSyntaxException ex ) {
177
            throw new IllegalArgumentException(ex);
178
        }
179
    }
180
}
(-)a/spring.beans/src/org/netbeans/modules/spring/beans/jumpto/SpringBeansTypeProvider.java (-85 / +7 lines)
Lines 56-61 Link Here
56
import org.netbeans.modules.spring.api.beans.model.SpringConfigModel;
56
import org.netbeans.modules.spring.api.beans.model.SpringConfigModel;
57
import org.netbeans.modules.spring.api.beans.model.SpringConfigModel.DocumentAccess;
57
import org.netbeans.modules.spring.api.beans.model.SpringConfigModel.DocumentAccess;
58
import org.netbeans.modules.spring.beans.ProjectSpringScopeProvider;
58
import org.netbeans.modules.spring.beans.ProjectSpringScopeProvider;
59
import org.netbeans.spi.jumpto.support.NameMatcher;
60
import org.netbeans.spi.jumpto.support.NameMatcherFactory;
59
import org.netbeans.spi.jumpto.type.SearchType;
61
import org.netbeans.spi.jumpto.type.SearchType;
60
import org.netbeans.spi.jumpto.type.TypeProvider;
62
import org.netbeans.spi.jumpto.type.TypeProvider;
61
import org.openide.filesystems.FileObject;
63
import org.openide.filesystems.FileObject;
Lines 92-98 Link Here
92
94
93
        final String searchText = context.getText();
95
        final String searchText = context.getText();
94
        final SearchType searchType = context.getSearchType();
96
        final SearchType searchType = context.getSearchType();
95
        final Matcher matcher = getMatcher(searchText, searchType);
97
        final NameMatcher matcher = NameMatcherFactory.createNameMatcher(searchText, searchType);
96
        if (matcher == null) {
98
        if (matcher == null) {
97
            return;
99
            return;
98
        }
100
        }
Lines 158-176 Link Here
158
160
159
                                for (SpringBean bean : beans) {
161
                                for (SpringBean bean : beans) {
160
                                    String id = bean.getId();
162
                                    String id = bean.getId();
161
                                    if (id != null && matcher.match(id)) {
163
                                    if (id != null && matcher.accept(id)) {
162
                                        currCache.add(new BeanTypeDescriptor(id, bean));
164
                                        currCache.add(new BeanTypeDescriptor(id, bean));
163
                                    }
165
                                    }
164
166
165
                                    for (String name : bean.getNames()) {
167
                                    for (String name : bean.getNames()) {
166
                                        if (matcher.match(name)) {
168
                                        if (matcher.accept(name)) {
167
                                            currCache.add(new BeanTypeDescriptor(name, bean));
169
                                            currCache.add(new BeanTypeDescriptor(name, bean));
168
                                        }
170
                                        }
169
                                    }
171
                                    }
170
                                }
172
                                }
171
173
172
                                for (String alias : fileBeans.getAliases()) {
174
                                for (String alias : fileBeans.getAliases()) {
173
                                    if (matcher.match(alias)) {
175
                                    if (matcher.accept(alias)) {
174
                                        currCache.add(new BeanAliasTypeDescriptor(alias, fo));
176
                                        currCache.add(new BeanAliasTypeDescriptor(alias, fo));
175
                                    }
177
                                    }
176
                                }
178
                                }
Lines 192-198 Link Here
192
        if (cache != null) {
194
        if (cache != null) {
193
            ArrayList<AbstractBeanTypeDescriptor> beans = new ArrayList<AbstractBeanTypeDescriptor>(cache.size());
195
            ArrayList<AbstractBeanTypeDescriptor> beans = new ArrayList<AbstractBeanTypeDescriptor>(cache.size());
194
            for (AbstractBeanTypeDescriptor beanTypeDescriptor : cache) {
196
            for (AbstractBeanTypeDescriptor beanTypeDescriptor : cache) {
195
                if (cacheRefresh || matcher.match(beanTypeDescriptor.getSimpleName())) {
197
                if (cacheRefresh || matcher.accept(beanTypeDescriptor.getSimpleName())) {
196
                    beans.add(beanTypeDescriptor);
198
                    beans.add(beanTypeDescriptor);
197
                }
199
                }
198
            }
200
            }
Lines 212-295 Link Here
212
        lastRefreshText = null;
214
        lastRefreshText = null;
213
        lastRefreshSearchType = null;
215
        lastRefreshSearchType = null;
214
    }
216
    }
215
216
    private interface Matcher {
217
218
        boolean match(String str);
219
    }
220
    
221
    private static Pattern camelCaseBlock = Pattern.compile("(\\p{javaUpperCase}(?:\\p{javaLowerCase}|\\d|\\.|\\-)*)"); // NOI18N
222
223
    private Matcher getMatcher(String searchText, SearchType searchType) {
224
        switch (searchType) {
225
            case EXACT_NAME:
226
                return new StringMatcher(searchText, false, true);
227
            case CASE_INSENSITIVE_EXACT_NAME:
228
                return new StringMatcher(searchText, false, false);
229
            case PREFIX:
230
                return new StringMatcher(searchText, true, true);
231
            case CASE_INSENSITIVE_PREFIX:
232
                return new StringMatcher(searchText, true, false);
233
            case REGEXP:
234
                String regex = searchText + "*"; // NOI18N
235
236
                regex = regex.replace("*", ".*").replace('?', '.'); // NOI18N
237
238
                return new RegExpMatcher(regex, true);
239
            case CASE_INSENSITIVE_REGEXP:
240
                regex = searchText + "*"; // NOI18N
241
242
                regex = regex.replace("*", ".*").replace('?', '.'); // NOI18N
243
244
                return new RegExpMatcher(regex, false);
245
            case CAMEL_CASE:
246
                java.util.regex.Matcher m = camelCaseBlock.matcher(searchText);
247
                StringBuilder sb = new StringBuilder();
248
                while (m.find()) {
249
                    sb.append(m.group()).append("(?:\\p{javaLowerCase}|\\d|\\.|\\-)*"); // NOI18N
250
251
                }
252
                sb.append(".*"); // NOI18N
253
                return new RegExpMatcher(sb.toString(), false);
254
        }
255
256
        assert false; // probably a new type got added to SearchType, would need fixing on our part
257
258
        return null;
259
    }
260
261
    private static final class RegExpMatcher implements Matcher {
262
263
        private final String regex;
264
        private final boolean caseSensitive;
265
        private final Pattern pattern;
266
267
        public RegExpMatcher(String regex, boolean caseSensitive) {
268
            this.regex = regex;
269
            this.caseSensitive = caseSensitive;
270
            this.pattern = caseSensitive ? Pattern.compile(regex) : Pattern.compile(regex, Pattern.CASE_INSENSITIVE);
271
        }
272
273
        public boolean match(String str) {
274
            return pattern.matcher(str).matches();
275
        }
276
    }
277
278
    private static final class StringMatcher implements Matcher {
279
280
        private final String searchText;
281
        private final boolean prefix;
282
        private final boolean caseSensitive;
283
284
        public StringMatcher(String searchText, boolean prefix, boolean caseSensitive) {
285
            this.searchText = searchText;
286
            this.prefix = prefix;
287
            this.caseSensitive = caseSensitive;
288
        }
289
290
        public boolean match(String str) {
291
            int length = prefix ? searchText.length() : Math.max(str.length(), searchText.length());
292
            return str.regionMatches(caseSensitive, 0, searchText, 0, length);
293
        }
294
    }
295
}
217
}

Return to bug 185168