27
27
import com .github .javaparser .utils .SourceRoot ;
28
28
import com .google .common .collect .Table ;
29
29
import com .google .common .collect .Tables ;
30
+ import com .ibm .cldk .javaee .CRUDFinderFactory ;
31
+ import com .ibm .cldk .javaee .utils .enums .CRUDOperationType ;
32
+ import com .ibm .cldk .javaee .utils .enums .CRUDQueryType ;
30
33
import com .ibm .cldk .entities .*;
31
34
import com .ibm .cldk .utils .Log ;
32
35
import org .apache .commons .lang3 .tuple .Pair ;
@@ -409,6 +412,18 @@ private static Pair<String, Callable> processCallableDeclaration(CallableDeclara
409
412
410
413
callableNode .setAccessedFields (getAccessedFields (body , classFields , typeName ));
411
414
callableNode .setCallSites (getCallSites (body ));
415
+ callableNode .setCrudOperations (
416
+ callableNode .getCallSites ().stream ()
417
+ .map (CallSite ::getCrudOperation )
418
+ .filter (Objects ::nonNull )
419
+ .collect (Collectors .toList ())
420
+ );
421
+ callableNode .setCrudQueries (
422
+ callableNode .getCallSites ().stream ()
423
+ .map (CallSite ::getCrudQuery )
424
+ .filter (Objects ::nonNull )
425
+ .collect (Collectors .toList ())
426
+ );
412
427
callableNode .setVariableDeclarations (getVariableDeclarations (body ));
413
428
callableNode .setCyclomaticComplexity (getCyclomaticComplexity (callableDecl ));
414
429
@@ -420,16 +435,19 @@ private static boolean isEntryPointMethod(CallableDeclaration callableDecl) {
420
435
return isServletEntrypointMethod (callableDecl ) || isJaxRsEntrypointMethod (callableDecl ) || isSpringEntrypointMethod (callableDecl ) | isStrutsEntryPointMethod (callableDecl );
421
436
}
422
437
438
+ @ SuppressWarnings ("unchecked" )
423
439
private static boolean isServletEntrypointMethod (CallableDeclaration callableDecl ) {
424
440
return ((NodeList <Parameter >) callableDecl .getParameters ()).stream ()
425
441
.anyMatch (parameter -> parameter .getType ().asString ().contains ("HttpServletRequest" ) ||
426
442
parameter .getType ().asString ().contains ("HttpServletResponse" )) && callableDecl .getAnnotations ().stream ().anyMatch (a -> a .toString ().contains ("Override" ));
427
443
}
428
444
445
+ @ SuppressWarnings ("unchecked" )
429
446
private static boolean isJaxRsEntrypointMethod (CallableDeclaration callableDecl ) {
430
447
return callableDecl .getAnnotations ().stream ().anyMatch (a -> a .toString ().contains ("POST" ) || a .toString ().contains ("PUT" ) || a .toString ().contains ("GET" ) || a .toString ().contains ("HEAD" ) || a .toString ().contains ("DELETE" ));
431
448
}
432
449
450
+ @ SuppressWarnings ("unchecked" )
433
451
private static boolean isSpringEntrypointMethod (CallableDeclaration callableDecl ) {
434
452
return callableDecl .getAnnotations ().stream ().anyMatch (a ->
435
453
a .toString ().contains ("GetMapping" ) ||
@@ -455,10 +473,11 @@ private static boolean isSpringEntrypointMethod(CallableDeclaration callableDecl
455
473
);
456
474
}
457
475
476
+ @ SuppressWarnings ("unchecked" )
458
477
private static boolean isStrutsEntryPointMethod (CallableDeclaration callableDecl ) {
459
478
// First check if this method is in a Struts Action class
460
479
Optional <Node > parentNode = callableDecl .getParentNode ();
461
- if (! parentNode .isPresent () || !(parentNode .get () instanceof ClassOrInterfaceDeclaration )) {
480
+ if (parentNode .isEmpty () || !(parentNode .get () instanceof ClassOrInterfaceDeclaration )) {
462
481
return false ;
463
482
}
464
483
@@ -631,6 +650,7 @@ private static List<String> getAccessedFields(Optional<BlockStmt> callableBody,
631
650
* @param callableBody callable to compute call-site information for
632
651
* @return list of call sites
633
652
*/
653
+ @ SuppressWarnings ({"OptionalUsedAsFieldOrParameterType" })
634
654
private static List <CallSite > getCallSites (Optional <BlockStmt > callableBody ) {
635
655
List <CallSite > callSites = new ArrayList <>();
636
656
if (callableBody .isEmpty ()) {
@@ -680,8 +700,31 @@ private static List<CallSite> getCallSites(Optional<BlockStmt> callableBody) {
680
700
}
681
701
// resolve arguments of the method call to types
682
702
List <String > arguments = methodCallExpr .getArguments ().stream ().map (SymbolTable ::resolveExpression ).collect (Collectors .toList ());
703
+ // Get argument string from the callsite
704
+ List <String > listOfArgumentStrings = methodCallExpr .getArguments ().stream ().map (Expression ::toString ).collect (Collectors .toList ());
705
+ // Determine if this call site is potentially a CRUD operation.
706
+ CRUDOperation crudOperation = null ;
707
+ Optional <CRUDOperationType > crudOperationType = findCRUDOperation (declaringType , methodCallExpr .getNameAsString ());
708
+ if (crudOperationType .isPresent ()) {
709
+ // We found a CRUD operation, so we need to populate the details of the call site this CRUD operation.
710
+ int lineNumber = methodCallExpr .getRange ().isPresent () ? methodCallExpr .getRange ().get ().begin .line : -1 ;
711
+ crudOperation = new CRUDOperation ();
712
+ crudOperation .setLineNumber (lineNumber );
713
+ crudOperation .setOperationType (crudOperationType .get ());
714
+ }
715
+ // Determine if this call site is potentially a CRUD query.
716
+ CRUDQuery crudQuery = null ;
717
+ Optional <CRUDQueryType > crudQueryType = findCRUDQuery (declaringType , methodCallExpr .getNameAsString (), Optional .of (listOfArgumentStrings ));
718
+ if (crudQueryType .isPresent ()) {
719
+ // We found a CRUD query, so we need to populate the details of the call site this CRUD query.
720
+ int lineNumber = methodCallExpr .getRange ().isPresent () ? methodCallExpr .getRange ().get ().begin .line : -1 ;
721
+ crudQuery = new CRUDQuery ();
722
+ crudQuery .setLineNumber (lineNumber );
723
+ crudQuery .setQueryType (crudQueryType .get ());
724
+ crudQuery .setQueryArguments (listOfArgumentStrings );
725
+ }
683
726
// add a new call site object
684
- callSites .add (createCallSite (methodCallExpr , methodCallExpr .getNameAsString (), receiverName , declaringType , arguments , returnType , calleeSignature , isStaticCall , false , accessSpecifier ));
727
+ callSites .add (createCallSite (methodCallExpr , methodCallExpr .getNameAsString (), receiverName , declaringType , arguments , returnType , calleeSignature , isStaticCall , false , crudOperation , crudQuery , accessSpecifier ));
685
728
}
686
729
687
730
for (ObjectCreationExpr objectCreationExpr : callableBody .get ().findAll (ObjectCreationExpr .class )) {
@@ -700,11 +743,52 @@ private static List<CallSite> getCallSites(Optional<BlockStmt> callableBody) {
700
743
}
701
744
702
745
// add a new call site object
703
- callSites .add (createCallSite (objectCreationExpr , "<init>" , objectCreationExpr .getScope ().isPresent () ? objectCreationExpr .getScope ().get ().toString () : "" , instantiatedType , arguments , instantiatedType , calleeSignature , false , true , AccessSpecifier .NONE ));
746
+ callSites .add (createCallSite (objectCreationExpr , "<init>" , objectCreationExpr .getScope ().isPresent () ? objectCreationExpr .getScope ().get ().toString () : "" , instantiatedType , arguments , instantiatedType , calleeSignature , false , true , null , null , AccessSpecifier .NONE ));
704
747
}
705
748
706
749
return callSites ;
707
750
}
751
+ @ SuppressWarnings ("OptionalUsedAsFieldOrParameterType" )
752
+ private static Optional <CRUDQueryType > findCRUDQuery (String declaringType , String nameAsString , Optional <List <String >> arguments ) {
753
+ return CRUDFinderFactory .getCRUDFinders ().map (
754
+ finder -> {
755
+ if (finder .isReadQuery (declaringType , nameAsString , arguments )) {
756
+ return CRUDQueryType .READ ;
757
+ }
758
+ else if (finder .isWriteQuery (declaringType , nameAsString , arguments )) {
759
+ return CRUDQueryType .WRITE ;
760
+ }
761
+ else if (finder .isNamedQuery (declaringType , nameAsString , arguments )) {
762
+ return CRUDQueryType .NAMED ;
763
+ }
764
+ else
765
+ return null ;
766
+ })
767
+ .filter (Objects ::nonNull )
768
+ .findFirst ();
769
+ }
770
+
771
+ private static Optional <CRUDOperationType > findCRUDOperation (String declaringType , String nameAsString ) {
772
+ return CRUDFinderFactory .getCRUDFinders ().map (
773
+ finder -> {
774
+ if (finder .isCreateOperation (declaringType , nameAsString )) {
775
+ return CRUDOperationType .CREATE ;
776
+ }
777
+ else if (finder .isReadOperation (declaringType , nameAsString )) {
778
+ return CRUDOperationType .READ ;
779
+ }
780
+ else if (finder .isUpdateOperation (declaringType , nameAsString )) {
781
+ return CRUDOperationType .UPDATE ;
782
+ }
783
+ else if (finder .isDeleteOperation (declaringType , nameAsString )) {
784
+ return CRUDOperationType .DELETE ;
785
+ }
786
+ else
787
+ return null ;
788
+ })
789
+ .filter (Objects ::nonNull )
790
+ .findFirst ();
791
+ }
708
792
709
793
/**
710
794
* Creates and returns a new CallSite object for the given expression, which
@@ -719,7 +803,20 @@ private static List<CallSite> getCallSites(Optional<BlockStmt> callableBody) {
719
803
* @param isConstructorCall
720
804
* @return
721
805
*/
722
- private static CallSite createCallSite (Expression callExpr , String calleeName , String receiverExpr , String receiverType , List <String > arguments , String returnType , String calleeSignature , boolean isStaticCall , boolean isConstructorCall , AccessSpecifier accessSpecifier ) {
806
+ private static CallSite createCallSite (
807
+ Expression callExpr ,
808
+ String calleeName ,
809
+ String receiverExpr ,
810
+ String receiverType ,
811
+ List <String > arguments ,
812
+ String returnType ,
813
+ String calleeSignature ,
814
+ boolean isStaticCall ,
815
+ boolean isConstructorCall ,
816
+ CRUDOperation crudOperation ,
817
+ CRUDQuery crudQuery ,
818
+ AccessSpecifier accessSpecifier
819
+ ) {
723
820
CallSite callSite = new CallSite ();
724
821
callSite .setMethodName (calleeName );
725
822
callSite .setReceiverExpr (receiverExpr );
@@ -733,6 +830,8 @@ private static CallSite createCallSite(Expression callExpr, String calleeName, S
733
830
callSite .setPublic (accessSpecifier .equals (AccessSpecifier .PUBLIC ));
734
831
callSite .setProtected (accessSpecifier .equals (AccessSpecifier .PROTECTED ));
735
832
callSite .setUnspecified (accessSpecifier .equals (AccessSpecifier .NONE ));
833
+ callSite .setCrudOperation (crudOperation );
834
+ callSite .setCrudQuery (crudQuery );
736
835
if (callExpr .getRange ().isPresent ()) {
737
836
callSite .setStartLine (callExpr .getRange ().get ().begin .line );
738
837
callSite .setStartColumn (callExpr .getRange ().get ().begin .column );
0 commit comments