2727import com .github .javaparser .utils .SourceRoot ;
2828import com .google .common .collect .Table ;
2929import 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 ;
3033import com .ibm .cldk .entities .*;
3134import com .ibm .cldk .utils .Log ;
3235import org .apache .commons .lang3 .tuple .Pair ;
@@ -409,6 +412,18 @@ private static Pair<String, Callable> processCallableDeclaration(CallableDeclara
409412
410413 callableNode .setAccessedFields (getAccessedFields (body , classFields , typeName ));
411414 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+ );
412427 callableNode .setVariableDeclarations (getVariableDeclarations (body ));
413428 callableNode .setCyclomaticComplexity (getCyclomaticComplexity (callableDecl ));
414429
@@ -420,16 +435,19 @@ private static boolean isEntryPointMethod(CallableDeclaration callableDecl) {
420435 return isServletEntrypointMethod (callableDecl ) || isJaxRsEntrypointMethod (callableDecl ) || isSpringEntrypointMethod (callableDecl ) | isStrutsEntryPointMethod (callableDecl );
421436 }
422437
438+ @ SuppressWarnings ("unchecked" )
423439 private static boolean isServletEntrypointMethod (CallableDeclaration callableDecl ) {
424440 return ((NodeList <Parameter >) callableDecl .getParameters ()).stream ()
425441 .anyMatch (parameter -> parameter .getType ().asString ().contains ("HttpServletRequest" ) ||
426442 parameter .getType ().asString ().contains ("HttpServletResponse" )) && callableDecl .getAnnotations ().stream ().anyMatch (a -> a .toString ().contains ("Override" ));
427443 }
428444
445+ @ SuppressWarnings ("unchecked" )
429446 private static boolean isJaxRsEntrypointMethod (CallableDeclaration callableDecl ) {
430447 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" ));
431448 }
432449
450+ @ SuppressWarnings ("unchecked" )
433451 private static boolean isSpringEntrypointMethod (CallableDeclaration callableDecl ) {
434452 return callableDecl .getAnnotations ().stream ().anyMatch (a ->
435453 a .toString ().contains ("GetMapping" ) ||
@@ -455,10 +473,11 @@ private static boolean isSpringEntrypointMethod(CallableDeclaration callableDecl
455473 );
456474 }
457475
476+ @ SuppressWarnings ("unchecked" )
458477 private static boolean isStrutsEntryPointMethod (CallableDeclaration callableDecl ) {
459478 // First check if this method is in a Struts Action class
460479 Optional <Node > parentNode = callableDecl .getParentNode ();
461- if (! parentNode .isPresent () || !(parentNode .get () instanceof ClassOrInterfaceDeclaration )) {
480+ if (parentNode .isEmpty () || !(parentNode .get () instanceof ClassOrInterfaceDeclaration )) {
462481 return false ;
463482 }
464483
@@ -631,6 +650,7 @@ private static List<String> getAccessedFields(Optional<BlockStmt> callableBody,
631650 * @param callableBody callable to compute call-site information for
632651 * @return list of call sites
633652 */
653+ @ SuppressWarnings ({"OptionalUsedAsFieldOrParameterType" })
634654 private static List <CallSite > getCallSites (Optional <BlockStmt > callableBody ) {
635655 List <CallSite > callSites = new ArrayList <>();
636656 if (callableBody .isEmpty ()) {
@@ -680,8 +700,31 @@ private static List<CallSite> getCallSites(Optional<BlockStmt> callableBody) {
680700 }
681701 // resolve arguments of the method call to types
682702 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+ }
683726 // 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 ));
685728 }
686729
687730 for (ObjectCreationExpr objectCreationExpr : callableBody .get ().findAll (ObjectCreationExpr .class )) {
@@ -700,11 +743,52 @@ private static List<CallSite> getCallSites(Optional<BlockStmt> callableBody) {
700743 }
701744
702745 // 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 ));
704747 }
705748
706749 return callSites ;
707750 }
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+ }
708792
709793 /**
710794 * Creates and returns a new CallSite object for the given expression, which
@@ -719,7 +803,20 @@ private static List<CallSite> getCallSites(Optional<BlockStmt> callableBody) {
719803 * @param isConstructorCall
720804 * @return
721805 */
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+ ) {
723820 CallSite callSite = new CallSite ();
724821 callSite .setMethodName (calleeName );
725822 callSite .setReceiverExpr (receiverExpr );
@@ -733,6 +830,8 @@ private static CallSite createCallSite(Expression callExpr, String calleeName, S
733830 callSite .setPublic (accessSpecifier .equals (AccessSpecifier .PUBLIC ));
734831 callSite .setProtected (accessSpecifier .equals (AccessSpecifier .PROTECTED ));
735832 callSite .setUnspecified (accessSpecifier .equals (AccessSpecifier .NONE ));
833+ callSite .setCrudOperation (crudOperation );
834+ callSite .setCrudQuery (crudQuery );
736835 if (callExpr .getRange ().isPresent ()) {
737836 callSite .setStartLine (callExpr .getRange ().get ().begin .line );
738837 callSite .setStartColumn (callExpr .getRange ().get ().begin .column );
0 commit comments