Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: novaworx/syntax/KeywordMap.java


1   /*
2   Novaworx Development Environment
3   Copyright (C) 2000-2003 Mark Soderquist
4   Portions Copyright (C) 1998-2001 Slava Pestov
5   Portions Copyright (C) 1999-2000 Mike Dillon
6   
7   This program is free software; you can redistribute it and/or modify
8   it under the terms of the GNU General Public License as published by
9   the Free Software Foundation; either version 2 of the License, or
10  (at your option) any later version.
11  
12  This program is distributed in the hope that it will be useful,
13  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  GNU General Public License for more details.
16  
17  You should have received a copy of the GNU General Public License
18  along with this program; if not, write to:
19  
20  Free Software Foundation, Inc.
21  59 Temple Place, Suite 330
22  Boston, MA 02111-1307 USA
23  */
24  
25  package novaworx.syntax;
26  
27  import java.util.Vector;
28  import javax.swing.text.Segment;
29  
30  /**
31  A <code>KeywordMap</code> is similar to a hashtable in that it maps keys
32  to values. However, the keys are Swing segments. This allows lookups of
33  text substrings without the overhead of creating a new string object.
34  
35  @author Slava Pestov
36  @author Mike Dillon
37  @author Mark Soderquist
38  */
39  public class KeywordMap {
40  
41    private Keyword[] maKeywords;
42    private boolean mbIgnoreCase;
43    private StringBuffer moNoWordSeparators;
44    protected int miMapLength;
45  
46    /**
47    Create a new <code>KeywordMap</code>.
48  
49    @param mbIgnoreCase True if keys are case insensitive
50    */
51    public KeywordMap( boolean abIgnoreCase) {
52      this( abIgnoreCase, 52 );
53    }
54  
55    /**
56    Create a new <code>KeywordMap</code>.
57  
58    @param mbIgnoreCase True if the keys are case insensitive.
59    @param miMapLength The number of 'buckets' to create.
60    A value of 52 will give good performance for most maps.
61    */
62    public KeywordMap(boolean abIgnoreCase, int aiMapLength) {
63      miMapLength = aiMapLength;
64      mbIgnoreCase = abIgnoreCase;
65      moNoWordSeparators = new StringBuffer();
66      maKeywords = new Keyword[ aiMapLength ];
67    }
68  
69    /**
70    Look up a key.
71  
72    @param aoText The text segment.
73    @param aiOffset The offset of the substring within the text segment.
74    @param aiLength The length of the substring.
75    */
76    public byte lookup( Segment aoText, int aiOffset, int aiLength ) {
77      if( aiLength == 0 ) return Token.NULL;
78      Keyword oKeyword = maKeywords[ getSegmentMapKey( aoText, aiOffset, aiLength) ];
79      while( oKeyword != null) {
80        if( aiLength != oKeyword.maKeyword.length ) {
81          oKeyword = oKeyword.moNext;
82          continue;
83        }
84        if( SyntaxUtilities.regionMatches( mbIgnoreCase, aoText, aiOffset, oKeyword.maKeyword ) ) {
85          return oKeyword.myID;
86        }
87        oKeyword = oKeyword.moNext;
88      }
89      return Token.NULL;
90    }
91  
92    /**
93    Adds a key-value mapping.
94  
95    @param keyword The key
96    @param id The value
97    */
98    public void add( String asKeyword, byte ayID ) {
99      int iKey = getStringMapKey( asKeyword );
100 
101     char[] aKeyword = asKeyword.toCharArray();
102 
103     // Complete-word command needs a list of all
104     // non-alphanumeric characters used in a keyword map.
105 loop:
106       for(int iIndex = 0; iIndex < aKeyword.length; iIndex++ ) {
107       char cChar = aKeyword[ iIndex ];
108       if( !Character.isLetterOrDigit( cChar ) ) {
109         for(int iSeparatorIndex = 0; iSeparatorIndex < moNoWordSeparators.length(); iSeparatorIndex++) {
110           if( moNoWordSeparators.charAt( iSeparatorIndex ) == cChar ) continue loop;
111         }
112 
113         moNoWordSeparators.append( cChar );
114       }
115     }
116 
117     maKeywords[ iKey ] = new Keyword( aKeyword, ayID, maKeywords[ iKey ] );
118   }
119 
120   /**
121   Returns all non-alphanumeric characters that appear in the
122   keywords of this keyword maKeywords.
123   */
124   public String getNonAlphaNumericChars() {
125     return moNoWordSeparators.toString();
126   }
127 
128   /**
129   Returns an array containing all keywords in this keyword map.
130   */
131   public String[] getKeywords() {
132     Vector vVector = new Vector(100);
133     for(int iIndex = 0; iIndex < maKeywords.length; iIndex++ ) {
134       Keyword oKeyword = maKeywords[ iIndex ];
135       while( oKeyword != null ) {
136         vVector.addElement( new String( oKeyword.maKeyword) );
137         oKeyword = oKeyword.moNext;
138       }
139     }
140     String[] aReturn = new String[ vVector.size() ];
141     vVector.copyInto( aReturn );
142     return aReturn;
143   }
144 
145   /**
146   Returns true if the keyword maKeywords is set to be case insensitive,
147   false otherwise.
148   */
149   public boolean getIgnoreCase() {
150     return mbIgnoreCase;
151   }
152 
153   /**
154   Sets if the keyword maKeywords should be case insensitive.
155   @param mbIgnoreCase True if the keyword maKeywords should be case
156   insensitive, false otherwise.
157   */
158   public void setIgnoreCase( boolean abIgnoreCase ) {
159     mbIgnoreCase = abIgnoreCase;
160   }
161 
162   protected int getStringMapKey( String asString ) {
163     return (
164       Character.toUpperCase( asString.charAt( 0 ) ) +
165       Character.toUpperCase( asString.charAt( asString.length() - 1 ) )
166     ) % miMapLength;
167   }
168 
169   protected int getSegmentMapKey( Segment aoSegment, int aiOffset, int aiLength ) {
170     return (
171       Character.toUpperCase( aoSegment.array[ aiOffset ] ) +
172       Character.toUpperCase( aoSegment.array[ aiOffset + aiLength - 1 ] )
173     ) % miMapLength;
174   }
175 
176   private class Keyword {
177 
178     public char[] maKeyword;
179     public byte myID;
180     public Keyword moNext;
181 
182     public Keyword( char[] aaKeyword, byte ayID, Keyword aoNext ) {
183       maKeyword = aaKeyword;
184       myID = ayID;
185       moNext = aoNext;
186     }
187 
188   }
189 
190 }