001: package isql;
002:
003: import java.util.ArrayList;
004:
005: /** this document has the ability to complete words or or expand abbreviations
006: * from a list of possible expansions.
007: * It is intended that the abbreviations come from a file
008: * whereas the completion is 'smart'/context sensitive such as names of
009: * tables and columns, or classnames/method names.
010: *
011: * THis implementation uses a String[] but we should create a default
012: * which uses a Model which can then be used for customization keeping
013: * the String array as one constructor.
014: * @author rahul kumar, 2001
015: */
016: public class TabExpander implements ITabExpander {
017:
018: /** stores the current word typed by user on which we are tabbing.
019: * We would revert to this word if he doesnt accept any substitution */
020: String _pattern = null;
021: /** stores all strings used by tab method, set by caller */
022: String[] _arrCache;
023: /** stores strings matched by last tab, for further tabs by user */
024: private String[] _arrMatched;
025: /** stores the index in _arrMatched of the last word shown to user
026: */
027: private int _matchedindex = -1;
028:
029: public TabExpander() {
030:
031: _arrCache = new String[] { "" }; // hopefully to prevent crashes
032: // temporary since databast connection is down
033: _arrCache = new String[] { "solution", "solution_rules",
034: "solutions", "registration", "registration_info",
035: "registry" };
036: //if none loaded
037:
038: }
039:
040: // does throw a NPE if space followed by tab
041: //
042: /* this is how you would use from a Document
043: public void insertString(int offs, String str, AttributeSet a)
044: throws BadLocationException {
045:
046: String repls;
047: if (str == null || str.length()==0) return;
048: char lc = str.charAt(str.length()-1);
049: // name completion
050: if (lc == '\t'){
051: if (_pattern == null){
052: _pattern = getLastWord(offs, str);
053: if ( (_pattern.length()==1 &&
054: Character.isWhitespace(_pattern.charAt(0))) ){
055: insertString(offs, str, a);
056: System.err.println( "returning" + str);
057: return;
058: }
059: // get the matches for the last word entered
060: previous = next;
061: next = getNextExpansion ( _pattern );
062: if (next == null){
063: _pattern = null;
064: insertString(offs, str, a); // let the entered word go
065: return;
066: }
067: } // there is a last word already, show next one
068:
069: // first time, update string with new word
070: if (previous==null){
071: remove(offs-_pattern.length(),_pattern.length());
072: super.insertString(offs-_pattern.length(), next, null);
073: return;
074: }
075: else
076: // next time update previous replacement with new
077: // one
078: if (next != null){
079: remove(offs-next.length(),previous.length());
080:
081: super.insertString(offs- previous.length(), next, null);
082: return;
083: }
084: else
085: super.insertString(offs, str, a); // replace orig word
086: } // tabbed
087: else
088: // abbreviation - the user entered a whitespace char
089: if (Character.isWhitespace(lc)){
090: String last = getLastWord(offs, str);
091: // get the expansion from abbrev hashtable
092: if ( (repls=(String)htabbr.get(last))!=null){
093: remove(offs-last.length(),last.length());
094: super.insertString(offs-last.length(), repls+lc, ctable);}
095: else
096: super.insertString(offs, str, a);
097: }
098: else
099: // character was not WS char, let things happen
100: // normally
101: super.insertString(offs, str, a);
102: _pattern=null;
103: }
104: */
105: /** searches backwards are returns the last word before the cursor.
106: * Will return a space or tab if there are multiple whitespace
107: * characters.
108: */
109: /*
110: private String getLastWord( int offset, String str) throws BadLocationException{
111: String lastline;
112: int spos = 0;
113: lastline = getText(0, offset);
114:
115: int i = offset -1;
116: while (i-- > spos){
117: if (Character.isWhitespace(lastline.charAt(i)))
118: break;
119: }
120: // i contains the last space
121: i++;
122: if (i<0)i=0; // added since space in beg throws SOB ex
123: return lastline.substring(i);
124: }
125: */
126: /** sets the cache - required at start of program.
127: */
128: public void setTabTable(String[] tabs) {
129: _arrCache = tabs;
130: }
131:
132: /** finds matched strings in the cached array, does a startsWith
133: * and not a equals: ABC will return ABC, ABCD, ABCDE etc.
134: * returns null if no match or if cache not set.
135: */
136: private String[] getMatches(String patt) {
137: if (_arrCache == null || _arrCache.length == 0)
138: return null;
139: ArrayList v = new ArrayList();
140: int len = patt.length();
141: for (int i = 0; i < _arrCache.length; i++) {
142: // check if patt is not longer than array else subst throws
143: // up
144: if (patt.length() <= _arrCache[i].length()
145: && _arrCache[i].substring(0, len).equals(patt))
146: v.add(_arrCache[i]);
147: }
148: String s[] = new String[v.size()];
149: s = (String[]) v.toArray(s);
150: return s;
151: }
152:
153: /** expands the given pattern, returning the match at count
154: * position. USer would start with 0, and continue till null is
155: * returned.
156: */
157: public String expand(String patt, int count) {
158: if (patt != _pattern) {
159: _pattern = null;
160: _arrMatched = getMatches(patt);
161: if (_arrMatched == null)
162: return null;
163: _pattern = patt;
164: }
165: if (count >= 0 && count <= _arrMatched.length)
166: return (_arrMatched[count]);
167: else
168: return null;
169: }
170:
171: /** returns expansions for a string. Caller would just send in a
172: * string and keep calling this until a null is returned.
173: * Caller would either call getNextExpansion or expand, whatever
174: * suits his needs better.
175: */
176: public String getNextExpansion(String patt) {
177: if (patt != _pattern)
178: _matchedindex = 0;
179: else
180: _matchedindex++;
181:
182: return expand(patt, _matchedindex);
183: }
184:
185: /* ---------
186: if (patt != _pattern){
187: _matchedindex = -1;
188: _pattern = null;
189: _arrCache = getMatches(patt);
190: if (_arrCache != null){
191: _matchedindex = 0;
192: _pattern = patt;
193: return (_arrCache[_matchedindex]);
194: }
195: else
196: return null;
197: }
198: else {
199: _matchedindex++;
200: if (_matchedindex<=_arrMatched.length)
201: return (_arrCache[_matchedindex]);
202: }
203: _matchedindex=-1;
204: _pattern = null;
205: return null;
206: */
207:
208: /** returns all expansions for the previously searched pattern
209: */
210: public String[] getExpansions() {
211: return _arrCache;
212: }
213:
214: /** returns expansions for the given string. Has no impact on
215: * existing searches.
216: */
217: public String[] getExpansions(String patt) {
218: return getMatches(patt);
219: }
220:
221: }
|