11package org .hibernate .tool .ide .completion ;
22
3- import java .util .ArrayList ;
4- import java .util .Arrays ;
5- import java .util .Collections ;
6- import java .util .HashMap ;
7- import java .util .Iterator ;
8- import java .util .List ;
9- import java .util .Map ;
10-
113import org .hibernate .grammars .hql .HqlLexer ;
124
13- /**
14- * The HQLAnalyzer can answer certain questions about a HQL String.
15- *
16- * @author leon, max.andersen@jboss.com
17- */
5+ import java .util .*;
6+
187public class HQLAnalyzer {
198
20- /** Defines the HQL keywords. Based on hql.g antlr grammer in 2005 ;) */
21- private static String [] hqlKeywords = { "between" , "class" , "delete" ,
22- "desc" , "distinct" , "elements" , "escape" , "exists" , "false" ,
23- "fetch" , "from" , "full" , "group" , "having" , "in" , "indices" ,
24- "inner" , "insert" , "into" , "is" , "join" , "left" , "like" , "new" ,
25- "not" , "null" , "or" , "order" , "outer" , "properties" , "right" ,
26- "select" , "set" , "some" , "true" , "union" , "update" , "versioned" ,
27- "where" , "and" , "or" , "as" ,"on" , "with" ,
28-
29- // -- SQL tokens --
30- // These aren't part of HQL, but recognized by the lexer. Could be
31- // usefull for having SQL in the editor..but for now we keep them out
32- // "case", "end", "else", "then", "when",
33-
34-
35- // -- EJBQL tokens --
36- "both" , "empty" , "leading" , "member" , "object" , "of" , "trailing" ,
9+ /** Defines the HQL keywords. Based on hql.g antlr grammer in 2005 ;) */
10+ private static final String [] hqlKeywords = { "between" , "class" , "delete" ,
11+ "desc" , "distinct" , "elements" , "escape" , "exists" , "false" ,
12+ "fetch" , "from" , "full" , "group" , "having" , "in" , "indices" ,
13+ "inner" , "insert" , "into" , "is" , "join" , "left" , "like" , "new" ,
14+ "not" , "null" , "or" , "order" , "outer" , "properties" , "right" ,
15+ "select" , "set" , "some" , "true" , "union" , "update" , "versioned" ,
16+ "where" , "and" , "or" , "as" ,"on" , "with" ,
17+
18+ // -- SQL tokens --
19+ // These aren't part of HQL, but recognized by the lexer. Could be
20+ // usefull for having SQL in the editor..but for now we keep them out
21+ // "case", "end", "else", "then", "when",
22+
23+
24+ // -- EJBQL tokens --
25+ "both" , "empty" , "leading" , "member" , "object" , "of" , "trailing" ,
3726 };
38-
27+
3928
4029 /**
41- * built-in function names. Various normal builtin functions in SQL/HQL.
42- * Maybe sShould try and do this dynamically based on dialect or
43- * sqlfunctionregistry
44- */
45- private static String [] builtInFunctions = {
46- // standard sql92 functions
47- "substring" , "locate" , "trim" , "length" , "bit_length" , "coalesce" ,
48- "nullif" , "abs" , "mod" , "sqrt" ,
49- "upper" ,
50- "lower" ,
51- "cast" ,
52- "extract" ,
30+ * built-in function names. Various normal builtin functions in SQL/HQL.
31+ * Maybe sShould try and do this dynamically based on dialect or
32+ * sqlfunctionregistry
33+ */
34+ private static final String [] builtInFunctions = {
35+ // standard sql92 functions
36+ "substring" , "locate" , "trim" , "length" , "bit_length" , "coalesce" ,
37+ "nullif" , "abs" , "mod" , "sqrt" ,
38+ "upper" ,
39+ "lower" ,
40+ "cast" ,
41+ "extract" ,
42+
43+ // time functions mapped to ansi extract
44+ "second" , "minute" , "hour" , "day" ,
45+ "month" ,
46+ "year" ,
5347
54- // time functions mapped to ansi extract
55- "second" , "minute" , "hour" , "day" ,
56- "month" ,
57- "year" ,
48+ "str" ,
5849
59- "str" ,
50+ // misc functions - based on oracle dialect
51+ "sign" , "acos" , "asin" , "atan" , "cos" , "cosh" , "exp" , "ln" , "sin" ,
52+ "sinh" , "stddev" , "sqrt" , "tan" , "tanh" , "variance" ,
6053
61- // misc functions - based on oracle dialect
62- "sign" , "acos" , "asin" , "atan" , "cos" , "cosh" , "exp" , "ln" , "sin" ,
63- "sinh" , "stddev" , "sqrt" , "tan" , "tanh" , "variance" ,
54+ "round" , "trunc" , "ceil" , "floor" ,
6455
65- "round" , "trunc" , "ceil" , "floor" ,
56+ "chr" , "initcap" , "lower" , "ltrim" , "rtrim" , "soundex" , "upper" ,
57+ "ascii" , "length" , "to_char" , "to_date" ,
6658
67- "chr" , "initcap" , "lower" , "ltrim " , "rtrim " , "soundex " , "upper " ,
68- "ascii " , "length " , "to_char " , "to_date " ,
59+ "current_date " , "current_time " , "current_timestamp " , "lastday " ,
60+ "sysday " , "systimestamp " , "uid " , "user " ,
6961
70- "current_date" , "current_time" , "current_timestamp" , "lastday" ,
71- "sysday" , "systimestamp" , "uid" , "user" ,
62+ "rowid" , "rownum" ,
7263
73- "rowid" , "rownum" ,
64+ "concat" , "instr" , "instrb" , "lpad" , "replace" , "rpad" , "substr" ,
65+ "substrb" , "translate" ,
7466
75- "concat" , "instr" , "instrb" , "lpad" , "replace" , "rpad" , "substr" ,
76- "substrb" , "translate" ,
67+ "substring" , "locate" , "bit_length" , "coalesce" ,
7768
78- "substring " , "locate " , "bit_length " , "coalesce " ,
69+ "atan2 " , "log " , "mod " , "nvl" , "nvl2" , "power " ,
7970
80- "atan2" , "log" , "mod" , "nvl " , "nvl2 " , "power " ,
71+ "add_months " , "months_between " , "next_day " ,
8172
82- "add_months" , "months_between " , "next_day" ,
73+ "max " , "min" , };
8374
84- "max" , "min" , };
85-
8675 static {
87- // to allow binary search
88- Arrays .sort (builtInFunctions );
89- Arrays .sort (hqlKeywords );
76+ // to allow binary search
77+ Arrays .sort (builtInFunctions );
78+ Arrays .sort (hqlKeywords );
9079 }
9180
92- protected SimpleHQLLexer getLexer (char chars [], int end ) {
93- return new AntlrSimpleHQLLexer (chars , end );
81+ protected SimpleHQLLexer getLexer (char [] chars ) {
82+ return new AntlrSimpleHQLLexer (chars );
9483 }
95-
96- protected SimpleHQLLexer getLexer (char chars []) {
97- return new AntlrSimpleHQLLexer (chars ,chars .length );
98- }
99-
84+
10085 /**
10186 * Returns true if the position is at a location where an entityname makes sense.
102- * e.g. "from Pr| where x"
103- * @param query
104- * @param cursorPosition
105- * @return
87+ * e.g. "from Pr| where x"
10688 */
10789 public boolean shouldShowEntityNames (String query , int cursorPosition ) {
108- return shouldShowEntityNames ( query .toCharArray (), cursorPosition );
90+ return shouldShowEntityNames ( query .toCharArray (), cursorPosition );
10991 }
110-
111- public boolean shouldShowEntityNames (char chars [] , int cursorPosition ) {
112- SimpleHQLLexer lexer = getLexer ( chars , cursorPosition );
92+
93+ public boolean shouldShowEntityNames (char [] chars , int cursorPosition ) {
94+ SimpleHQLLexer lexer = getLexer ( chars );
11395 int tokenId = -1 ;
11496 boolean show = false ;
11597 while ((tokenId = lexer .nextTokenId ()) != HqlLexer .EOF ) {
@@ -119,18 +101,17 @@ public boolean shouldShowEntityNames(char chars[], int cursorPosition) {
119101 (lexer .getTokenOffset () + lexer .getTokenLength ()) < cursorPosition ) {
120102 show = true ;
121103 } else if (tokenId != HqlLexer .DOT && tokenId != HqlLexer .AS && tokenId != HqlLexer .COMMA && tokenId != HqlLexer .IDENTIFIER && tokenId != HqlLexer .WS ) {
122- show = false ;
123- }
104+ show = false ;
105+ }
124106 }
125- return show ;
107+ return show ;
126108 }
127-
109+
128110 public List <SubQuery > getVisibleSubQueries (char [] chars , int position ) {
129- SubQueryList sqList = getSubQueries (chars , position );
111+ SubQueryList sqList = getSubQueries (chars , position );
130112 List <SubQuery > visible = new ArrayList <SubQuery >();
131- for (Iterator <SubQuery > iter = sqList .subQueries .iterator (); iter .hasNext ();) {
132- SubQuery sq = iter .next ();
133- if (sqList .caretDepth >= sq .depth && (sq .startOffset <= position || sq .endOffset >= position )) {
113+ for (SubQuery sq : sqList .subQueries ) {
114+ if (sqList .caretDepth >= sq .depth && (sq .startOffset <= position || sq .endOffset >= position )) {
134115 visible .add (sq );
135116 }
136117 }
@@ -140,16 +121,15 @@ public List<SubQuery> getVisibleSubQueries(char[] chars, int position) {
140121 public List <EntityNameReference > getVisibleEntityNames (char [] chars , int position ) {
141122 List <SubQuery > sqs = getVisibleSubQueries (chars , position );
142123 List <EntityNameReference > entityReferences = new ArrayList <EntityNameReference >();
143- for (Iterator <SubQuery > iter = sqs .iterator (); iter .hasNext ();) {
144- SubQuery sq = iter .next ();
145- entityReferences .addAll (sq .getEntityNames ());
146- }
124+ for (SubQuery sq : sqs ) {
125+ entityReferences .addAll (sq .getEntityNames ());
126+ }
147127 return entityReferences ;
148128 }
149129
150130 public SubQueryList getSubQueries (char [] query , int position ) {
151- SimpleHQLLexer syntax = getLexer ( query );
152- int numericId = -1 ;
131+ SimpleHQLLexer syntax = getLexer ( query );
132+ int numericId = -1 ;
153133 List <SubQuery > subQueries = new ArrayList <SubQuery >();
154134 int depth = 0 ;
155135 int caretDepth = 0 ;
@@ -163,15 +143,15 @@ public SubQueryList getSubQueries(char[] query, int position) {
163143 caretDepth = depth ;
164144 }
165145 } else if (numericId == HqlLexer .RIGHT_PAREN ) {
166- SubQuery currentDepthQuery = level2SubQuery .get (Integer . valueOf ( depth ) );
146+ SubQuery currentDepthQuery = level2SubQuery .get (depth );
167147 // We check if we have a query on the current depth.
168148 // If yes, we'll have to close it
169149 if (currentDepthQuery != null && currentDepthQuery .depth == depth ) {
170150 currentDepthQuery .endOffset = syntax .getTokenOffset ();
171- currentDepthQuery .tokenIds .add (Integer . valueOf ( numericId ) );
151+ currentDepthQuery .tokenIds .add (numericId );
172152 currentDepthQuery .tokenText .add (String .valueOf (query , syntax .getTokenOffset (), syntax .getTokenLength ()));
173153 subQueries .add (currentDepthQuery );
174- level2SubQuery .remove (Integer . valueOf ( depth ) );
154+ level2SubQuery .remove (depth );
175155 tokenAdded = true ;
176156 }
177157 depth --;
@@ -184,32 +164,33 @@ public SubQueryList getSubQueries(char[] query, int position) {
184164 case HqlLexer .UPDATE :
185165 case HqlLexer .DELETE :
186166 case HqlLexer .SELECT :
187- if (!level2SubQuery .containsKey (Integer . valueOf ( depth ) )) {
167+ if (!level2SubQuery .containsKey (depth )) {
188168 current = new SubQuery ();
189169 current .depth = depth ;
190170 current .startOffset = syntax .getTokenOffset ();
191- level2SubQuery .put (Integer .valueOf (depth ), current );
171+ level2SubQuery .put (depth , current );
172+ }
173+ if (current != null ) {
174+ current .tokenIds .add (numericId );
175+ current .tokenText .add (String .valueOf (query , syntax .getTokenOffset (), syntax .getTokenLength ()));
176+ break ;
192177 }
193- current .tokenIds .add (Integer .valueOf (numericId ));
194- current .tokenText .add (String .valueOf (query , syntax .getTokenOffset (), syntax .getTokenLength ()));
195- break ;
196178 default :
197179 if (!tokenAdded ) {
198- SubQuery sq = level2SubQuery .get (Integer . valueOf ( depth ) );
180+ SubQuery sq = level2SubQuery .get (depth );
199181 int i = depth ;
200182 while (sq == null && i >= 0 ) {
201- sq = level2SubQuery .get (Integer . valueOf ( i --) );
183+ sq = level2SubQuery .get (i --);
202184 }
203185 if (sq != null ) {
204- sq .tokenIds .add (Integer . valueOf ( numericId ) );
186+ sq .tokenIds .add (numericId );
205187 sq .tokenText .add (String .valueOf (query , syntax .getTokenOffset (), syntax .getTokenLength ()));
206188 }
207189 }
208190 }
209191 }
210- for (Iterator <SubQuery > iter = level2SubQuery .values ().iterator (); iter .hasNext ();) {
211- SubQuery sq = iter .next ();
212- sq .endOffset = syntax .getTokenOffset () + syntax .getTokenLength ();
192+ for (SubQuery sq : level2SubQuery .values ()) {
193+ sq .endOffset = syntax .getTokenOffset () + syntax .getTokenLength ();
213194 subQueries .add (sq );
214195 }
215196 Collections .sort (subQueries );
@@ -219,11 +200,11 @@ public SubQueryList getSubQueries(char[] query, int position) {
219200 return sql ;
220201 }
221202
222-
203+
223204 /** Returns reference name found from position and backwards in the array.
224205 **/
225206 public static String getEntityNamePrefix (char [] chars , int position ) {
226- StringBuffer buff = new StringBuffer ();
207+ StringBuilder buff = new StringBuilder ();
227208 for (int i = position - 1 ; i >= 0 ; i --) {
228209 char c = chars [i ];
229210 if (c == '.' || Character .isJavaIdentifierPart (c )) {
@@ -242,13 +223,13 @@ public static class SubQueryList {
242223 public List <SubQuery > subQueries ;
243224 }
244225
245-
226+
246227 static String [] getHQLKeywords () {
247228 return hqlKeywords ;
248229 }
249-
230+
250231 static String [] getHQLFunctionNames () {
251232 return builtInFunctions ;
252233 }
253-
234+
254235}
0 commit comments