1313import com .trigersoft .jaque .expression .UnaryExpression ;
1414
1515import java .util .List ;
16+ import java .util .function .Predicate ;
1617import java .util .stream .Collectors ;
1718
1819/**
@@ -24,11 +25,15 @@ public class ToSqlVisitor implements ExpressionVisitor<StringBuilder> {
2425 private LinkedListStack <List <ConstantExpression >> arguments ;
2526 private StringBuilder sb ;
2627 private Expression body ;
28+ private StringComparisonTypes comparisonType ;
29+ private boolean stringComparisonNegation ;
30+ private Expression javaMethodParameter ;
2731
2832 ToSqlVisitor (String prefix ) {
2933 this .prefix = prefix ;
3034 this .sb = new StringBuilder ();
3135 this .arguments = new LinkedListStack <>();
36+ this .comparisonType = StringComparisonTypes .NONE ;
3237 }
3338
3439 /**
@@ -51,8 +56,9 @@ private static String toSqlOp(int expressionType) {
5156 return " IS NOT NULL" ;
5257 case ExpressionType .Convert :
5358 return "" ;
59+ default :
60+ return ExpressionType .toString (expressionType );
5461 }
55- return ExpressionType .toString (expressionType );
5662 }
5763
5864 /**
@@ -81,7 +87,16 @@ public StringBuilder visit(BinaryExpression e) {
8187 if (quote ) sb .append ('(' );
8288
8389 e .getFirst ().accept (this );
84- sb .append (' ' ).append (toSqlOp (e .getExpressionType ())).append (' ' );
90+ if (comparisonType == StringComparisonTypes .NONE ) {
91+ sb .append (' ' ).append (toSqlOp (e .getExpressionType ())).append (' ' );
92+ } else {
93+ if (stringComparisonNegation ) {
94+ sb .append (" NOT LIKE " );
95+ stringComparisonNegation = false ;
96+ } else {
97+ sb .append (" LIKE " );
98+ }
99+ }
85100 e .getSecond ().accept (this );
86101
87102 if (quote ) sb .append (')' );
@@ -106,7 +121,25 @@ public StringBuilder visit(ConstantExpression e) {
106121 return sb ;
107122 }
108123 if (e .getValue () instanceof String ) {
109- return sb .append ("'" ).append (e .getValue ().toString ()).append ("'" );
124+ sb .append ("'" );
125+ switch (comparisonType ) {
126+ case STARTS_WITH :
127+ sb .append (e .getValue ()).append ('%' );
128+ comparisonType = StringComparisonTypes .NONE ;
129+ break ;
130+ case ENDS_WITH :
131+ sb .append ('%' ).append (e .getValue ());
132+ comparisonType = StringComparisonTypes .NONE ;
133+ break ;
134+ case CONTAINS :
135+ sb .append ('%' ).append (e .getValue ()).append ('%' );
136+ comparisonType = StringComparisonTypes .NONE ;
137+ break ;
138+ case NONE :
139+ default :
140+ sb .append (e .getValue ());
141+ }
142+ return sb .append ("'" );
110143 }
111144 return sb .append (e .getValue ().toString ());
112145 }
@@ -129,6 +162,10 @@ public StringBuilder visit(InvocationExpression e) {
129162 if (!list .isEmpty ()) {
130163 arguments .push (list );
131164 }
165+ Predicate <String > testForJavaMethod = s -> s .endsWith ("startsWith" ) || s .endsWith ("endsWith" ) || s .endsWith ("contains" );
166+ if (testForJavaMethod .test (e .getTarget ().toString ())) {
167+ javaMethodParameter = e .getArguments ().get (0 );
168+ }
132169 return e .getTarget ().accept (this );
133170 }
134171
@@ -163,6 +200,19 @@ public StringBuilder visit(DelegateExpression e) {
163200 @ Override
164201 public StringBuilder visit (MemberExpression e ) {
165202 String name = e .getMember ().getName ();
203+ //for support for Java methods
204+ if (name .equals ("startsWith" )) {
205+ comparisonType = StringComparisonTypes .STARTS_WITH ;
206+ return Expression .binary (ExpressionType .Equal , e .getInstance (), javaMethodParameter ).accept (this );
207+ }
208+ if (name .equals ("endsWith" )) {
209+ comparisonType = StringComparisonTypes .ENDS_WITH ;
210+ return Expression .binary (ExpressionType .Equal , e .getInstance (), javaMethodParameter ).accept (this );
211+ }
212+ if (name .equals ("contains" )) {
213+ comparisonType = StringComparisonTypes .CONTAINS ;
214+ return Expression .binary (ExpressionType .Equal , e .getInstance (), javaMethodParameter ).accept (this );
215+ }
166216 name = name .replaceAll ("^(get)" , "" );
167217 name = name .substring (0 , 1 ).toLowerCase () + name .substring (1 );
168218 if (prefix == null ) {
@@ -198,11 +248,21 @@ public StringBuilder visit(ParameterExpression e) {
198248 @ Override
199249 public StringBuilder visit (UnaryExpression e ) {
200250 if (e .getExpressionType () == ExpressionType .LogicalNot ) {
201- sb .append ("!" );
251+ //for support for negated Java methods
252+ var name = ((MemberExpression ) ((InvocationExpression ) e .getFirst ()).getTarget ()).getMember ().getName ();
253+ if (name .equals ("startsWith" ) || name .equals ("endsWith" ) || name .equals ("contains" )) {
254+ stringComparisonNegation = true ;
255+ } else {
256+ sb .append ("!" );
257+ }
202258 return e .getFirst ().accept (this );
203259 }
204260 e .getFirst ().accept (this );
205261 return sb .append (toSqlOp (e .getExpressionType ()));
206262 }
207263
264+ private enum StringComparisonTypes {
265+ NONE , STARTS_WITH , ENDS_WITH , CONTAINS
266+ }
267+
208268}
0 commit comments