Java method invocation parser? - java

I need to parse certain method invocation calls including the whole signature out of some Java classes, e.g.
public class MyClass {
public void myMthod() {
// ... some code here
result = someInstance.someOtherMethod(param1, param2);
// ... some other code here
}
}
As a result I would like to get something like:
serviceName = someInstance
methodName = someOtherMethod
arguments = {
argument = java.lang.String,
argument = boolean
}
result = java.lang.Long
What would be the fastest way to achieve this?
I was thinking about using a RegEx parser. The problem there is there are several occurence patterns, e.g.
a)
result = someInstance.someOtherMethod(getSomething(), param);
b)
result =
getSomeInstance().someOtherMethod(param);
c)
result = getSomeInstance()
.someOtherMethod(
getSomethingElse(), null, param);
Any help would be really appreciated! Thanks!

Don't use regex! Use tools that understand java.
Use either:
A source code parser (e.g. javaparser)
Byte code analysis (e.g. ASM)
An aspect (AspectJ)
In both source parser and ASM, you will write a visitor that scans for method invocations.
For javaparser: Read this page, extend VoidVisitorAdapter and override
public void visit(MethodCallExpr n, A arg)
Sample Code:
public static void main(final String[] args) throws Exception{
parseCompilationUnit(new File("src/main/java/foo/bar/Phleem.java"));
}
public static void parseCompilationUnit(final File sourceFile)
throws ParseException, IOException{
final CompilationUnit cu = JavaParser.parse(sourceFile);
cu.accept(new VoidVisitorAdapter<Void>(){
#Override
public void visit(final MethodCallExpr n, final Void arg){
System.out.println(n);
super.visit(n, arg);
}
}, null);
}
The problem here is that you only have the object names, not the object types, so you will also have to keep a local Map of variable / field to type and that's where things get messy. Perhaps ASM is the easier choice, after all.
For ASM: read this tutorial page to get started

Realistically you can't parse a typical programming langauge like Java with regular expressions; you need a full parser. In your case, you need a parser that is capable of parsing arbitrary substrings (in this case, function call nonterminals) of the langauge, and those are much harder to find.
You also didn't say how you intended to find (and delimit) the calls of interest, before you decided to call them. You are likely to need Java symbol table data in order to just pick the method names you want; oherwise,
how will you know that "someService" resolves the actual service class that you care about, and not just some arbitrary class that happens to have what appears to be the right name?

Related

Reason for Java IDE generating methods with void return type when extract method shortcut is used

I was recently reading a java class where the person had created methods via IDE shortcut( extract method shortcut ). All methods had a return type of void and what was supposed to be return type was passed as input parameter for the method. Below is an example of what i'm referring to.
public void multiply(Integer first, Integer second, Integer result){
result = first * second;
}
I was wondering if the above is a good way of doing things. I personally do not like the above way of creating methods. I think the method should have been like below.
public Integer multiply(Integer first, Integer second, Integer result){
return first * second;
}
But in IntelliJ/Eclipse when we do extract method mostly creates method like above.
Can someone please let me know why IDE's usually create void method when we use the extract method shortcut and is the 1st style of method definition a good practice at all?
If the method being called isn't being assigned to a variable, Eclipse has no way to know what the return value is supposed to be.
Presumably, the original code looked something like this:
public static void main(String args[]){
Integer result = 0;
multiply(1,3,result);
}
There's no way for Eclipse to divine that multiply is supposed to return anything, so it defaults to void. If you want to infer return values, have it be assigned to a variable like so:
public static void main(String args[]){
Integer result = 0;
result = multiply(1,3,result);
}

Java 8 functional interfaces verses functions

Suppose I have an application that needs to apply several custom transformation on strings. The needs will grow by time. The following two approaches do exactly the same thing, but I am wondering which one is more beneficial in the long run. Are they the same? Or, does one offer more benefits than the other as the number of transforms increase and vary?
Suppose we have these:
public static final String PL = "(";
public static final String PR = ")";
public static final String Q1 = "'";
Here is each approach's setup and usage.
Approach 1:
#FunctionalInterface
public interface StringFunction {
String applyFunction(String s);
}
public class StrUtils {
public static String transform(String s, StringFunction f) {
return f.applyFunction(s);
}
public static String putInQ1(String s) {
return Q1.concat(s).concat(Q1);
}
public static String putInParens(String s) {
return PL.concat(s).concat(PR);
}
// and so on...
}
Which I would use like this:
System.out.println(StrUtils.transform("anSqlStr", StrUtils::putInQ1));
System.out.println(StrUtils.transform("sqlParams", StrUtils::putInParens));
Approach 2:
Here, I use straightforward Function:
Function<String, String> putInQ1 = n -> Q1.concat(n).concat(Q1);
Function<String, String> putInParens = n -> PL.concat(n).concat(PR);
// and so on...
Which I would use like this:
System.out.println(putInQ1.apply("anSqlStr");
System.out.println(putInParens.apply("sqlParams");
You sketched two ways of offering a certain functionality
The first one is to explicitly offer it as a method
public static String putInQ1(String s) {
return Q1.concat(s).concat(Q1);
}
which is supposed to be used via a method reference.
The second one is to offer it as a Function object:
Function<String, String> putInQ1 = n -> Q1.concat(n).concat(Q1);
(Here, you did not say where these instances should be located. I assume that you would also create a class that contained all these Function instances as (possibly public static final fields)
JBNizet mentioned a third option: You could use the methods directly, and not via method references. Indeed, the purpose of the transform function is not entirely clear. The only justification for this would be that you want to pass in arbitrary method references there, but these method references would just be Function objects - like in the second approach...
However, in a technical sense, the difference is not so large. Just to illustrate the point: Both approaches can trivially be converted into each other! The method can be implemented based on the function object
public static String putInQ1(String s) {
return putInQ1.apply(s);
}
And a function object can be created from the method reference:
Function<String, String> putInQ1 = StringUtils::putInQ1;
So the main question may be: How do you want to offer this functionality to the user of your library?
For this, consider the use case the you have an input string, and want to put it into ( parentheses ), and the result into ' single quotes ':
String doItWithMethodReferences(String input) {
String result = input;
result = StrUtils.transform(result, StrUtils::putInParens);
result = StrUtils.transform(result, StrUtils::putInQ1);
return result;
}
String doItWithFunctionObjects(String input) {
String result = input;
result = StringFunctions.putInParens.apply(result);
result = StringFunctions.putInQ1.apply(result)
return result;
}
String doItWithMethods(String input) {
String result = input;
result = StrUtils.putInParens(result);
result = StrUtils.putInQ1(result);
return result;
}
You can see that there is hardly a difference between the approaches that would qualify one of them as "better" or "worse" than the other in terms of readability, except for the obvious fact that the last one is simpler than the first one by avoiding the unnecessary transform calls.
Of course, each of these methods could be written "more compactly", in a single line. But depending on the number and the structure of the operations, this could severely reduce the readability, and in fact, this leads to another point: I could imagine that extensibility may something to consider. Imagine you wanted to create a single operation that placed a string into '( single quotes and parentheses )' at once.
With methods:
public static String putInPandQ1(String s) {
return putInQ1(putInParens(s));
}
With functions:
Function<String, String> putInPandQ1 = putInParens.andThen(putInQ1);
I think that the andThen function would be a nice feature that helps to compose more complex string manipulations.
(But taking that arbitrarily far, one has to ask whether you are not actually attempting to implement a template engine or a new domain-specific programming language...)
A short note: All this seems fairly unrelated to performance. Whether you do return s0 + s1; or return s0.concat(s1) will often not matter, and in the few cases where it does matter, you can change the implementation later - because, given the functionality that is sketched in the question, the decision about using + or concat or some StringBuilder trickery is exactly that: An implementation detail.
And another note, as pointed out in the comments: Instead of defining your own StringFunction interface, you could use UnaryOperator<String>. Both are "structurally equal", but the first one is part of the standard API. Imagine that there are already many libraries out there, with methods that expect the standard UnaryOperator<String> as an argument. When you only have instances of your own StringFunction, then you may have to convert these instances so that your code can cooperate with other code. This is trivial, of course, but the interfaces in the functional package are carefully chosen to cover a large range of application cases, and I think that the interoperability between libraries can be greatly increased when programmers don't needlessly create new interfaces that already exist in the standard API. One could argue that the introduction of the StringFunction makes code easier, because it does not need the <String> generic parameter. But if you want this, then you should simply declare the iterface as interface StringFunction extends UnaryOperator<String> { }, which simply is a further specialization, and will keep the compatibility with other code. Additionally, you'll then conveniently inherit all the default methods from Function, like the andThen that I mentined above.
Why not simply define the method 'putInWhatever(String s, String left, String right) {
return left + s + right;
}
with overloaded variants in case left and right are equal. No complicated functional interfaces and lambda's needed

Is there a way in Java to have mutually exclusive options handled by the compiler?

I'm wondering if there's a way to declare a method that takes a String and an Enum, but only require the string to be used if a certain enum is used.
Example:
public enum SearchType {
REGEX,DEFAULT
}
public static List<File> Search(String path, SearchType search, String pattern) {
//do things
}
Ideally, the pattern string field would only be required for the programmer to specify if they used the specific SearchType.REGEX, and if you either forgot it, or included it on a SearchType.DEAFULT, your program would not compile.
As it stands, the programmer would have to pass in an empty string if they're using SearchType DEFAULT, and the the code must check using a couple of if statements for the mutually exclusive options. Right now I have it throwing an IllegalArgumentException if you include a pattern with DEFAULT or forget the pattern on a REGEX, since both of those things indicate the person using this function probably made a mistake.
My questions are:
Is this kind of compile-time parameter checking even possible with Java 8?
is there a more idiomatic/safe/logical way to handle this case?
This sounds like it would be handled by an Interface of some kind if it can even be done.
Thanks!
You should declare two methods: one method is called to do one job, not two. So here, you can declare:
public static List<File> search(String path);
and
public static List<File> search(String path, String pattern);
Your enum SearchType is useless in that case. Remember to add javadoc to your methods and the user won't be confused.
There is no way to do compile-time parameter checking in Java 8.
However, you could write this in a cleaner way with varargs. Something like this:
public static List<File> Search(String path, SearchType search, String... searchArgs) {
if (search == SearchType.REGEX) {
if (searchArgs.length != 1) {
throw new IllegalArgumentException("Improper number of arguments for regex search: Expected 1, got " + searchArgs.length);
}
//Do the search
}
if (search == SearchType.DEFAULT) {
if (searchArgs.length != 0) {
throw new IllegalArgumentException("Improper number of arguments for default search: Expected 0, got " + searchArgs.length);
}
//Do the search
}
}
That way, it can be called like this:
Search("C:\\", SearchType.REGEX, "[a]");
Search("C:\\", SearchType.DEFAULT);
You still won't receive a compile error if you call it the wrong way, though.

java cast and call a string as method on an object

I am using AOP to find the value of an instance variable before its going to be set and after it is set. So I am intercepting all setxxx methods and trying to do a getxxx before and after.
//actual instance
Object target = joinPoint.getTarget();
//Type of the instance
Class objectClass = target.getClass();
I want to call a string "getFirstName()" that is actually a method name on the actual instance (target). How can I do so
right now I can do the following
if (target instanceof User) {
instanceVarCurrentValue = ((User) target).getFirstName();
}
But i cannot check for instance of for all objects in my project and for each class I will have to check all properties
You need to use Reflection. You must find the method on class and invoke it.
Please see the below code:
public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
User user = new User();
String name = runMethod(user, "getFirstName");
System.out.println(name);
}
private static String runMethod(Object instance, String methodName) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
Method method = instance.getClass().getMethod(methodName);
return (String)method.invoke(instance);
}
The possible ways to solve this in Java is to write code that covers all cases with lots of if and else and instanceof expressions.
You will need to implement something like ObjectConverter as in this answer,
Or you can always use Java Reflection API.
My go-to solution for things like this is a handy library called jOOR - for 'Java Object Oriented Reflection'. It's a fluent wrapper around Java's reflection tools, which lets you write code like so:
String firstName = on(target).call("getFirstName").get();
With the above, ANY object 'target' with a method called getFirstName will work here, and the get() will (try to) cast the result as a string. Pretty handy if you know you only have to deal with a specific set of types that are guaranteed to have the methods you're interested in, but don't want to write and maintain an enormous if-else block.

Map of delegates in Java

I am trying to do a very simple command line library for interactive Java programs. You start the Java program and it prompts you for commands. The syntax is:
> action [object_1, [object_2, [... object_n] ... ]]
for example:
> addUser name "John Doe" age 42
Here action = "addUser", object_1 = "name", object_2 = "John Doe", object_3 = "age", object_4 = "42".
Everything after action is an object (that is, an action uses objects). You can see that the action and the object are simple strings. Object strings can also be converted to numbers if necessary.
My plan is that the user of this command line library would simply create methods (belonging to any suitable Java object) and assign each method to a specific action. The objects in the command line become parameters for the method the user assigns. A suitable class that implements a method for the example above would be:
class Foo {
public void addUserHandler(
String param1, String param2, String param3, Integer param4) {
do.someThing();
}
}
When a user types a command, the corresponding function assigned by the programmer gets called with the parameters specified in the command line.
I know that Java doesn't have function pointers (like C) or delegates (like C#) and the way to implement callbacks is through an interface, however, I don't see how can I use interfaces in this scenario. The problem I see with interfaces is that they have:
A fixed number of functions to be implemented
The functions to be implemented have a fixed declaration.
The problem with (1) is that the user of my library may decide to implement any number of functions, for as many actions as he wants to support. The problem with (2) is that the user would want to assign functions with descriptive names, like addUserHandler() for "addUSer" action.
If Java had delegates or function pointers I would just create a Map between Strings (representing actions) and delegates (for the actual implementation of the action in the program). I think I can emulate delegates with Reflection, but it is gory and I lose the type safety, as I'd have to use String names for classes and methods. Is there any better way?
Thanks,
If you want the user to get automagic type translation (e.g. from strings to ints), then reflection is the only way. if you make the user do the work, then you don't need reflection (and you get type safety):
your command interface:
public interface MyCommand {
public void execute(String[] args);
}
an implementation:
public class MyObj {
public void doSomething(String param1, Integer param2) {
}
private void register() {
mainApp.registerCommand("doSomething", new MyCommand() {
#Override public void execute(String[] args) {
doSomething(args[0], Integer.parseInt(args[1]));
}});
}
}
Kudos to you for the sheer awesomeness of this question. You're pretty much up against the limits of what Java can do. (Though, of course, delegating like you describe would be a breeze in any functional language.)
First of all, limitation #2 should not be an issue. As of 1.5, Java no longer restricts you to fixed declarations in methods. You can use an ellipsis to indicate a variable number of arguments, like so
public static double average( double... numbers ) {
double total = 0.0;
for (double d : numbers) {
total += d;
}
return total / numbers.length;
}
I'm not entirely sure how to get around limitation #1, but I'm thinking about something with generics and/or anonymous inner classes. I'm guessing here -- I haven't tried doing this myself -- but you could create a map of function names and delegate classes like so:
public interface Callback {...}
public interface AddUserCallBack extends Callback {...}
public class UserImpl<T extends Callback> {
public T getDelegateRoutine();
...
}
Generics in Java have some hair-pulling frustrations associated with them, primarily due to type erasure. You may need to juggle both interfaces and abstract base classes before you get it to do what you want. But something like this should work for you.
The reflective solution is not so bad. You can do something like (syntax may not be 100%, Java is not my best language and I've no compiler here):
interface Action {
public void Apply(object[] args);
}
class AddUser implements Action {
Type[] argTypes;
public AddUser() {
argTypes = {String, String, String, Integer};
}
public void Apply(object[] args) {
// Now interpret args based on the contents of argTypes, and do your thing.
// The map would look like "adduser" => new AddUser()
// and could be invoked as map["adduser"].Apply(args)
}
}
But as rtperson said, you are running up against some fundamental limits of Java. Almost any other modern language would serve you better.

Categories