We have a huge project where many methods have been declared upfront and implementations are in progress. All declared methods have a body which simply throws an exception, say, UnimplException.
Now since the methods have been declared and a valid (compilable) body has been provided, they can be called from within other methods.
Now the question is that is there any way to list all such unimplemented (having just a compilable body throwing a particular exception) methods given a particular method?
To illustrate more(the code is to convey the idea and not strictly compiler friendly):
class A {
methA () {
throw new UnimplException();
}
}
class B {
methB () {
// proper body
// and calls methA
A.methA();
// does something else
// and returns.
}
}
class C {
methC () {
// proper body
// calls methB
B.methB();
}
}
So, if we start from, say, methC, then we want to travel all the way down the method tree to reach to methA because methC calls methB (which is properly implemented and we are not interested) which in turn calls methA which is not properly implemented and that is what we want to find.
We want to search for all such unimplemented methods starting from a method and going few levels deep until we cover all such unimplemented methods.
We thought of JavaAssist but we aren't sure how to go down all the levels because it seems to be giving us all methods called from within a method but not recursively.
Any help is greatly appreciated :)
Have you seen this project: https://github.com/gousiosg/java-callgraph? This appears to do the Java introspection part, listing every method call from every method in a jar file. I'd try using that to do the heavy lifting of parsing your code, then just recurse through the results.
Something like:
Use the callgraph code to build a list of all method calls.
Save that data somewhere.
Recursively parse that structure to find matching methods.
So from your example, step 1 would give something like the following:
A:methA -> UnimplException:<init>
B:methB -> A:methA
C:methC -> B:methB
Then shove those in a Multimap and do a fairly straightforward recursive search:
// this is populated from the output of the callgraph code
com.google.common.collect.Multimap<String, String> methodMap;
void checkAllMethods() {
for (String method : methodMap.keySet()) {
List<String> callStack = new ArrayList<>();
if (doesMethodThrowUnimplException(method, callStack)) {
System.out.println(method);
// can print callStack too if interested
}
}
}
boolean doesMethodThrowUnimplException(String method, List<String> callStack) {
for (String child : methodMap.get(method)) {
// have to check the exact method name from callgraph
if (child.equals("UnimplException:<init>")) {
return true;
}
// recurse into child if not already seen
if (!callStack.contains(child)) {
callStack.add(child);
if (doesMethodThrowUnimplException(child, callStack)) {
return true;
}
callStack.remove(callStack.size() - 1);
}
}
return false;
}
Doesn't strictly satisfy your requirements as this will report any method which throws the UnimplException, not those who only throw the exception, but not sure if that matters.
Standard disclaimer - just typed this in - haven't compiled / run it, so may well be typos, but hopefully the idea helps.
Related
We're in the process of trying to identify everywhere that a specific type of object is used only to get a specific property from it, and pass that property into the method instead.
I'm thinking IntelliJ IDEA's "Structural Search" might be a good tool for this, but I'm not sure how to formulate the search template.
A concrete example:
public class MyClass {
public Long getId() {...}
public void setSomethingElse(int se) {...}
}
public class SomeOtherClasses {
public void shouldBeMatched(MyClass mc) {
doSomething();
mc.getId();
doSomethingElse();
}
public void shouldNotBeMatched(MyClass mc) {
doSomething();
mc.getId();
mc.setSomethingElse(14);
doSomethingElse();
}
public void alsoShouldNotBeMatched(MyClass mc) {
shouldBeMatched(mc);
}
}
In the above example, if I'm looking for methods that only use getId, then I should find shouldBeMatched, but not be bothered with shoudNotBeMatched and alsoShouldNotBeMatched, because they do something with the mc object other than call getId().
I'm thinking IntelliJ IDEA's "Structural Search" might be a good tool for this
And it is indeed. The documentation can be tough though.
Let's check Search templates, filters, and script constraints page. It goes as follows.
Let's say, you have a variable that matches a method, a toString()
method. Then this variable is actually a PsiMethod node. Retrieving
variable.parent will produce a PsiClass node, and so forth.
variable.text then will give you the entire text of the method. If you
just need the name of the method, you can use variable.name.
It seems that the task can be done by choosing the right template and writing a corresponding Groovy script.
The template is called methods of the class and can be found under Existing templates. They provide __context__variable to be used with a script.
We have to be sure matched methods have parameters. It is simple enough, just put a count filter on a $Parameter$ variable.
Then we need to extract the name of a parameter of desired type and see if it is called in the body of the method. The following script will do.
def parameters = __context__.getParameterList().getParameters();
def parameter = parameters.find { p -> p.getType().getName().equals('MyClass') };
if (parameter == null) return false;
String parameterName = parameter.getName();
String methodText = __context__.getText();
String occurrence = "${parameterName}.";
String methodCall = "${parameterName}.getId()";
return methodText.count(occurrence) > 0 && methodText.count(occurrence) == methodText.count(methodCall);
Put it in the $Method$ variable filter and verify the results.
This question is general, but I feel it is best explained with a specific example. Let's say I have a directory with many nested sub directories and in some of those sub directories there are text files ending with ".txt". A sample structure could be:
dir1
dir2
file1.txt
dir3
file2.txt
file3.txt
I'd be interested if there were a way in Java to build a method that could be called to return the successive text files:
TextCrawler crawler = new TextCrawler(new File("dir1"));
File textFile;
textFile = crawler.nextFile(); // value is file1.txt
textFile = crawler.nextFile(); // value is file2.txt
textFile = crawler.nextFile(); // value is file3.txt
Here is the challenge: No internal list of all the text files can be saved in the crawler object. That is trivial. In that case you'd simply build into the initialization a method that recursively builds the list of files.
Is there a general way of pausing a recursive method so that when it is called again it returns to the specific point in the stack where it left? Or will we have to write something that is specific to each situation and solutions necessarily have to vary for file crawlers, org chart searches, recursive prime finders, etc.?
If you want a solution that works on any recursive function, you can accept a Consumer object. It may look something like this:
public void recursiveMethod(Consumer<TreeNode> func, TreeNode node){
if(node.isLeafNode()){
func.accept(node);
} else{
//Perform recursive call
}
}
For a bunch of files, it might look like this:
public void recursiveMethod(Consumer<File> func, File curFile){
if(curFile.isFile()){
func.accept(curFile);
} else{
for(File f : curFile.listFiles()){
recursiveMethod(func, f);
}
}
}
You can then call it with:
File startingFile;
//Initialize f as pointing to a directory
recursiveMethod((File file)->{
//Do something with file
}, startingFile);
Adapt as necessary.
I think the state should be saved while you return from your recursive function, then you need to restore the state as you call that recursive function again. There is no generic way to save such a state, however a template can probably be created. Something like this:
class Crawler<T> {
LinkedList<T> innerState;
Callback<T> callback;
constructor Crawler(T base,Callback<T> callback) {
innerState=new LinkedList<T>();
innerState.push(base);
this.callback=callback; // I want functions passed here
}
T recursiveFunction() {
T base=innerState.pop();
T result=return recursiveInner(base);
if (!result) innerState.push(base); // full recursion complete
return result;
}
private T recursiveInner(T element) {
ArrayList<T> c=callback.getAllSubElements(element);
T d;
for each (T el in c) {
if (innerState.length()>0) {
d=innerState.pop();
c.skipTo(d);
el=d;
if (innerState.length()==0) el=c.getNext();
// we have already processed "d", if full inner state is restored
}
T result=null;
if (callback.testFunction(el)) result=el;
if ((!result) && (callback.recursiveFunction(el))) result=recursiveInner(el); // if we can recurse on this element, go for it
if (result) {
// returning true, go save state
innerState.push(el); // push current local state to "stack"
return result;
}
} // end foreach
return null;
}
}
interface Callback<T> {
bool testFunction(T element);
bool recursiveFunction(T element);
ArrayList<t> getAllSubElements(T element);
}
Here, skipTo() is a method that modifies the iterator on c to point to provided element. Callback<T> is a means to pass functions to class to be used as condition checkers. Say "Is T a folder" for recursive check, "Is T a *.txt" for return check, and "getAllSubclassElements" should also belong here. The for each loop is fron lack of knowledge on how to work with modifiable iterators in Java, please adapt to actual code.
The only way I can think of that would meet your exact requirement would be to perform the recursive tree walk in a separate thread, and have that thread deliver results back to the main thread one at a time. (For simplicity you could use a bounded queue for the delivery, but it is also possible to implement is using wait / notify, a lock object and a single shared reference variable.)
In Python, for example, this would be a good fit for coroutines. Unfortunately, Java doesn't have a direct equivalent.
I should add that using threads is likely to incur significant overhead in synchronization and thread context switching. Using a queue will reduce them to a degree provided that rate of "producing" and "consuming" is well matched.
The title might seem unsettling, but let me explain.
I'm facing an interesting challenge, where I have a hierarchy of classes that have associated an object that stores metadata related to each one of its attributes (an int-valued enum with edit flags like UPDATED or NO_UPDATE).
The problem comes when merging two objects, because I dont want to check EVERY field on a class to see if it was updated and skip or apply the changes.
My idea: Reflection.
All the objects are behind an interface, so I could use IObject.class.getMethods() and iterate over that array in this fashion:
IClass class = //Instance of the first class;
IAnotherClass anotherClass = //Instance of the second class;
for(Method m : IObject.class.getMethods()) {
if(m.getName().startsWith("get")) {
try {
//Under this method (which is a getter) I cast it on
//both classes who implement interfaces that extend an
//interface that defines the getters to make them
//consistent and ensure I'll invoke the same methods.
String propertyClass = (String)m.invoke(class);
String propertyAnotherClass = (String)m.invoke(anotherClass);
if(propertyClass != propertyAnotherClass) {
//Update attribute and attribute status.
}
} catch (Exception e) {
}
}
}
Is there another way to implement this or should I stick to lengthy methods invoking attribute per attribute and doing the checks like that?. The objects are not going to change that much and the architecture is quite modular, so there is not much update involved if the fields change but having to change a method like that worries me a little.
EDIT 1: I'm posting a working code of what I have got so far. This code is a solution for me but, tough it works, I'm using it as a last resource not because I have time to spend but because I don't want to rediscover the wheel. If I use it, I'll make a static list with the methods so I only have to fetch that list once, considering the fact that AlexR pointed out.
private static void merge(IClazz from, IClazz to) {
Method methods[] = from.getClass().getDeclaredMethods();
for(Method m : methods) {
if(m.getName().startsWith("get") && !m.getName().equals("getMetadata")) {
try {
String commonMethodAnchor = m.getName().split("get")[1];
if(!m.getReturnType().cast(m.invoke(from)).equals(m.getReturnType().cast(m.invoke(to)))) {
String setterMethodName = "set" + commonMethodAnchor;
Method setter = IClazz.class.getDeclaredMethod(setterMethodName, m.getReturnType());
setter.invoke(to, m.getReturnType().cast(m.invoke(from)));
//Updating metadata
String metadataMethodName = "set" + commonMethodAnchor + "Status";
Method metadataUpdater = IClazzMetadata.class.getDeclaredMethod(metadataMethodName, int.class);
metadataUpdater.invoke(to.getMetadata(), 1);
}
} catch (Exception e) {
}
}
}
}
metadataUpdater sets the value to 1 just to simulate the "UPDATED" flag I'm using on the real case scenario.
EDIT 3: Thanks Juan, David and AlexR for your suggestions and directions! They really pointed me to consider things I did not consider at first (I'm upvoting all your answers because all of them helped me).
After adding what AlexR sugegsted and checking jDTO and Apache Commons (finding out that in the end the general concepts are quite similar) I've decided to stick to my code instead of using other tools, since it is working given the object hierarchy and metadata structure of the solution and there are no exceptions popping up so far. The code is the one on the 2nd edit and I've placed it on a helper class that did the trick in the end.
Apache Commons Bean Utils may resolve your problem: http://commons.apache.org/beanutils/
If you want to copy all properties, try to use copyProperties: http://commons.apache.org/beanutils/v1.8.3/apidocs/src-html/org/apache/commons/beanutils/BeanUtils.html#line.134
Look an example from: http://www.avajava.com/tutorials/lessons/how-do-i-copy-properties-from-one-bean-to-another.html
FromBean fromBean = new FromBean("fromBean", "fromBeanAProp", "fromBeanBProp");
ToBean toBean = new ToBean("toBean", "toBeanBProp", "toBeanCProp");
System.out.println(ToStringBuilder.reflectionToString(fromBean));
System.out.println(ToStringBuilder.reflectionToString(toBean));
try {
System.out.println("Copying properties from fromBean to toBean");
BeanUtils.copyProperties(toBean, fromBean);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
System.out.println(ToStringBuilder.reflectionToString(fromBean));
System.out.println(ToStringBuilder.reflectionToString(toBean));
I think the best approach would be using proxy objects, either dynamic proxies or cglib enhancers or something like it, so you decorate the getters and setters and you can keep track of the changes there.
Hope it helps.
Your approach is OK, but keep in mind that getMethod() is much slower than invoke(), so if your code is performance critical you will probably want to cache the Method objects.
We have App A as main app. Now we build from it App B which uses a subset of App A's functionality.
App A stays like it is whereas app B only uses a subset of A
So I want to refactor the function without or with as little dublication as possible and with maximum readability.
So the function looks like this (it is actually longer, this is an excerpt):
class SomeClass {
Data prepareData() {
if (this.bothId==1 || this.appAid=2 /*or only relevant for appA*/) {
if(this.data==null) { /*appA*/
appAdoSmth(); /*appA*/
}
boolean merge=false; /*appA*/
if (this.data==null) { /*appA*/
merge=appAanalyze(data); /*appA*/
}
bothPrepare(merge);
} else if (bothIsRelevant()) {
if(appArelevant()) { /*appA*/
data=appAprepare(); /*appA*/
} else {
data=prepareBoth();
}
bothUpdateSomeValue();
}
}
How would you do it?
Other Answers address the general question of how to refactor code. They offer good advice, but I don't think it is what you are asking.
I think you are asking about possible refactorings of the code in your question.
It is hard to give an answer that is generally applicable, or even specifically applicable. (The sample code isn't your real code, and it is a little difficult to understand what it actually "means").
AndreasD gives one approach: break the big complicated nested if into separate methods.
Another approach is to use the Stragegy design pattern. Separate the code that is specific to each app into strategy classes. For example:
interface Strategy {
Data prepareData();
}
class GeneralStrategy implements Strategy {
Data prepareData() {
// do general preparation
}
}
class App1Strategy extends GeneralStrategy {
Data prepareData() {
// do app1-specific preparation
super.prepareData();
// do more app1-specific preparation
}
}
and so on.
I ideal world develop unit test that validates that existing implementation of your function works.
Then start changing code incrementally and run your test after every change.
It is hard to give your formal recommendation without knowing your code structure. But generally try to find duplicate code fragments, write methods that implement this logic with parameters and replace the duplicate fragments to your new method. Etc, etc.
Good luck.
Readbility can be improved by extracting some logic in separate methods. That is a refactoring method.
Data prepareData() {
if (this.bothId==1 || this.appAid=2 ) {
handleCase1(); // <- you'll find better names for the methods
} else if (bothIsRelevant()) {
handleCase2();
}
}
private void handleCase1() {
if(this.data==null) {
appAdoSmth();
}
boolean merge=false;
if (this.data==null) {
merge=appAanalyze(data);
}
bothPrepare(merge);
}
private handleCase2() {
if(appArelevant()) {
data=appAprepare();
} else {
data=prepareBoth();
}
bothUpdateSomeValue();
}
This doesn't reduce the number of if/else, of course, but it keeps the "main" method simple.
If I were you I would run a coverage report on this class. (e.g. http://ecobertura.johoop.de/ or http://www.eclemma.org/) This way Eclipse can show covered lines green and this helps you to identify the cases. With this aid it's much easier to separate green lines and pull them into methods.
How can I get the names of the methods invoked in each method declaration of a program using AST (Abstract Syntax Tree) parser? So far, I have managed to get all the names of the methods' declaration and all the names of the methods being invoked, but I want to know which method call which methods. For example, I want to see that method m1 calls methods mA and mB, while method m2 calls methods mC and mD, etc.
[EDIT 11/9/2011 IDB, transcribing newbie's extended comment back in the body of the original question. I hope I have transcribed it correctly. I hope the author comes back and revises as necessary]:
My problem seems to be that (Eclipse's) MethodDeclaration api doesn't have a GetInvokedMethodName function to call. Here is my code:
public class MethodVisitor extends ASTVisitor {
List<MethodDeclaration> methods = new ArrayList<MethodDeclaration>();
#Override public boolean visit(MethodDeclaration node) {
methods.add(node);
return super.visit(node); }
public List<MethodDeclaration> getMethods()
{ return methods; }
List<MethodInvocation> methods1 = new ArrayList<MethodInvocation>();
#Override public boolean visit(MethodInvocation node)
{ methods1.add(node);
return super.visit(node); }
public List<MethodInvocation> getMethods1()
{ return methods1; }
}
...
for (MethodDeclaration method : visitor .getMethods())
{ System.out.println("Method name: " + method.getName()
+ " Return type: " + method.getReturnType2()
+ " Is constructor: " + method.isConstructor()
+ " Method invoked: " + ASTNode.METHOD_INVOCATION );
); }
for (MethodInvocation method1 : visitor .getMethods1())
{ System.out.println("Method name invoked: " + method1.getName() ); }
I had the same problem. This was my solution to it:
final HashMap<MethodDeclaration, ArrayList<MethodInvocation>> invocationsForMethods =
new HashMap<MethodDeclaration, ArrayList<MethodInvocation>>();
CompilationUnit cu = (CompilationUnit) ap.createAST(null);
cu.accept(new ASTVisitor() {
private MethodDeclaration activeMethod;
#Override
public boolean visit(MethodDeclaration node) {
activeMethod = node;
return super.visit(node);
}
#Override
public boolean visit(MethodInvocation node) {
if (invocationsForMethods.get(activeMethod) == null) {
invocationsForMethods.put(activeMethod, new ArrayList<MethodInvocation>());
}
invocationsForMethods.get(activeMethod).add(node);
return super.visit(node);
}
});
Now, one can ask the invocationsForMethods.keySet() to get all the method declarations for the used AST and invocationsForMethods.get(key) returns all method invocations for the declaration given as a key.
If you want to know which specific method mB (of all the ones named "mB" throughout your vast array of classes) is invoked by m1, you need more than just the AST. You need a full symbol table, that binds each symbol use to the possible definitions that match it.
The process of computing such a symbol table is difficult for many languages and very hard for Java (but not nearly as bad as it is for C++). Somebody has to encode the rules of how an identifier is looked up in the face of (local) scopes, inheritance, overloads, implied casts, etc, and the Java reference manual devotes a significant portion of its content trying to explain that. You don't want to have to do this yourself.
What you really need is a full Java front end, that has both ASTs and the corresponding symbol tables, for each method you want to inspect. You can get this, I think, from interfaces to the (Sun?) Java compiler (I don't personally know how to do this), from the Jikes compiler, from the Eclipse Java AST (?) module, and from tools such as our Java Front End. Another approach is to process class files, which contain the method calls in JVM form, with the advavntage that the JVM instructions all have built with the benefit of a symbol table.
If you want to compute m1 calls mA calls mQ calls .... mZ, you need a tool that is willing to read in the entire source code base at once. The compilers won't do that for you, but you can use Eclipse or our front end to do that.