Eclipse: Programmatically manipulate class - java

I just came across the issue that I had 10 (or so) Java classes for all of which I wanted to:
Add a formal parameter "String newparam" to their constructor
Add this as an actual parameter to the super() call to the super class constructor (thus, the result should be super(..., newparam)).
The reason is, obviously, that the common super class of those classes now has one constructor parameter more and all extending classes had to adapt.
I just can't believe that I need to do this by hand for all classes. Eclipse must have all required concepts like "constructor", "parameter" etc. in its internals. Any way to create a script for this?
I apologize if this is trivial/well known, I have to confess that I really don't know and appreciate any hints.

Changing the constructor signature of every subclass might have to be done with some kind of script. I don't think an IDE would infer the new parameter automatically in each constructor since each subclass could potentially use the new parameter differently.
Since you're using Eclipse, you can at somewhat skip your second requirement by selecting your superclass's constructor and hitting alt+shift+c (shortcut for refactor -> Change method signature...).
When you add the parameter via the GUI provided, all references to that constructor (such as the super calls in the extending classes) will be updated as well. You can even define a default value if you want.
Then if desired you can modify each extending class's constructor to also include the new parameter (by hand, sadly).

Thank you for comments and answers. It currently seems that there is no (widely) known Eclipse-built-in approach to do what I want.
Which is, in short:
Add a new constructor parameter to the super class and, at the same time,
create
the same parameter in the constructors of all extending classes and pass this
parameter through to the super class constructor
It should be noted, however, that the function
Add a new constructor parameter to the super class and add a default value for this parameter to all extending classes
Does work via refactor -> Change method signature... (thanks #Zircon).
A rather obvious solution in case you really have a lot of classes would be to write a script. A Java class was proposed by brahimfes which would have the advantage of not requiring a new language or a new working environment since my question is Java-specific. I also think that maybe a sed script could do the trick. I did, however, not try to, first, recognize the correct lines (constructor and super class constructor call, even though the second one is trivial) and, second, identify the correct position to add the parameters and, third, actually add them. Might work, I didn't try, I just have doubts about how long you would work on such a script until it works with no errors.
Now the solution I finally went for.
I realized that I always have the same key strokes (after I added the new parameter manually to the superclass constructor) in each subclass:
Select the constructor line.
Put the cursor at the and and backtrack 3 positions (parenthesis).
Add the formal parameter.
Go down one line.
Go to the end of this line (which always happens to be the super() call) and backtrack one position.
Add the actual parameter.
There are programs out there allowing to create makros of this kind, I got a trial version of one of them (I'm on a Mac) and did it this way.
Of course, this is still not actually a solution to my question and thus I won't mark this post as a solution. While I now have a makro that that relieves me of almost all typing, I still have to open each class in the editor manually, click the correct line and then fire the makro.
This program will still save me time in the future for similar requirements. But it is not what I hoped it to be, which would be some Eclipse-built-in scripting language with access to Java syntax elements for a more high-level access then regular expressions can offer.

Related

How to detect java local variables by an interface type and then find methods called on them?

I have some (maybe) strange requirements - I wanted to detect definitions of local (method) variables of a given interface name. When finding such a variable I would like to detect which methods (set/get*) will be called on this variable.
I tried Javassist without luck, and now I have a deeper look into ASM, but not sure if it is possible what I wanted.
The reason for this is that I like to generated a dependency graph with GraphViz of beans that depend on the same data structure.
If this thing is possible could somebody please give me a hint on how it could be done? Maybe there are other Frameworks that could do?
01.09.2015
To make things more clear:
The interface is self written - the target of the whole action is to create a dependency graph in the first step automatically - later on a graphical editor should be implemented that is based on the dependencies.
I wonder how FindBugs/PMD work, because they also use the byte code and detect for example null pointer calls (variable not initialized and method will be called on it). So I thought that I could implement my idea in the same way. The whole code is Spring based - maybe this opens another solution to the point? Last but not least I could work on a source-jar?
While thinging about the problem - would it be possible via ASM/javassist to detect all available methods from the interface and find calls to them in the other classes?
I’m afraid, what you want to do is not possible. In compiled Java code, there are no local variables in the form you have in the source code. Methods use stack frames which have memory reserved for local variables, which is addressed by a numerical index. The type is implied by what instructions write to it and may change throughout the method’s code as the memory may get reused for different variables having a disjunct scope. The names on the other hand are completely irrelevant.
When bytecode gets verified, the effect of all instructions to the stack frame will get modeled to infer the type of each stack frame slot at each point of the execution so that the validity of all operations can be checked. Starting with class file version 50, there will be StackMapTable attributes aiding the process by containing explicit type information, but only for code with branches. For sequential code, the type of variables still has to be derived by inference.
These inferred types are not necessarily the declared types. E.g., on the byte code level, there will be no difference between
CharSequence cs="foo";
cs.charAt(0);
and
String s="foo";
((CharSequence)s).charAt(0);
In both cases, there will be a storage of a String constant into a local variable followed by the invocation of an interface method. The inferred type will be String in both cases and the invocation of a CharSequence method considered valid as String implements CharSequence.
This disproves the idea of detecting that there is a local variable declared using the CharSequence (interface) type, as the actual declared type is irrelevant and not stored in the regular byte code.
There are, however, debugging attributes containing information about the local variables, see the LocalVariableTable attribute and libraries like ASM will tell you about the declarations if such information is present. But you can’t rely on these optional information. E.g. Oracle’s JRE libraries are by default shipped without them.
I don't sure I understood exacly what you want but .
you can use implement on each object ,
evry object that have getter you can implement it with class called getable .
and then you could do stuff only on object that have the function that you implement from the class getable .
https://docs.oracle.com/javase/tutorial/java/IandI/createinterface.html

Overload JNI Method

I have an existing JNI method with two parameters. Been around for a while, in use, so I don't want to just change it lest the wrath of angry customers be unleashed.
But, I now need to make an adjustment.
So, I thought, make a second overloaded method with the extra parameter and deprecate the two-parameter version. That part went fine, jar builds and runs with no issues.
The problem is in the C++ side... I defined two methods, one being a wrapper for the other (two parameter calls the three parameter version), but, when I went to export the two methods, I receive:
Error 1 error C2733: second C linkage of overloaded function 'Java_com_xxx' not allowed
So, what do I do to keep the old method name and add a new method with new parameters? Is this doable?
Run javah on your Java file declaring the native methods and you will see that you need two different Java_com_xxx functions. The C-level declarations must be unique.

Extending fluent interface

I'm starting using Fluent Assertions and I like it a lot, but wonder if it's possible to extend the existing tests in a general way like this:
add method hasSizeAtLeast(int limit) in GroupAssert
add method startsWithIgnoringCase(String prefix) in StringAssert
use alternatives like x.either().isIn(someSet).or().isNull()
These are just examples what I could need soon. I can do some workaround for each of them, but then I lose the readability and the easy of use of the fluent interface.
My last example is meant to throw iff both x.isIn(someSet) and x.isNull() do.
Here is a post by the author about opening up his API for extending assertions on already handled types. Lesson #1 in particular discusses the change to un-finalize classes. The post also gives an example of sub-classing StringAssert as MyStringAssert.
However, it looks like you cannot extend classes such as StringAssert in a way that maintains the "fluency" of the API. The StringAssert class isn't final, but still it doesn't allow you to parameterize its type (i.e. the "this" type that's returned by methods in StringAssert itself) in subclasses. For example, let's say you add a method checkFoo in MyStringAssert. As you discovered, the following is invalid because the original StringAssert methods return StringAssert:
new MyStringAssert("abcd").contains("a").checkFoo(); // compile-time error!
You only can call your subclass's methods first, which is valid but kind of lame:
new MyStringAssert("abcd").checkFoo().contains("a"); // compiles
You might consider contacting the author, or even submitting a patch to his git project. A possible solution would be to add the parameterized type back into StringAssert, and also provide the StringAssert concrete type via an anonymous subclass within Assertions.assertThat(String), which is the recommended entry point anyway. Then, everybody else can subclass StringAssert as you described. I haven't tested this suggestion either, but it seems to make sense...

Groovy: Dynamically addings methods with a specific signature

So, I need to dynamically create (or inject) methods into an object that have a specific return type and method signature, because a Java tool we're using will be finding this methods via Reflection and checks for void type. Method names will be determined at runtime.
Using metaClass. = { ... } however adds a closure which doesn't show up as a regular method (even if it can be used as one) and also has a return type.
I can't modify the method finding code, and it it not Groovy-aware.
I can't use methodMissing() or invokeMethod() because the method needs to actually exist. If I could overload class.getMethods() I think it would be possible, but I can't figure out how.
Is there any way to do this in Groovy?
You could use AST Transformations to add the code at compile time, but it wont work on classes that you don't compile, so I'm guessing that probably wont work.
You could probably replace the object with a CGLIB based proxy. If you can be more specific about the code in question...
EDIT: A little more info. Groovy metaClass magic is not available in Java unless the Java code were to explicitly call groovyClass.invokeMethod("someMethod",args);. So there isn't a way to do what you're asking with MetaClasses. CGLIB maybe.

trying to use only one method name

When I was programming a Form Validator in PHP, when creating new methods, I needed to increase the number of arguments in old methods.
When I was learning Java, when I read that extends is to not touch previously tested, working code, I thought I shouldn't have increased the number of arguments in the old methods, but overridden the old methods with the new methods.
Imagine if you are to verify if a field is empty in one part of the form, in an other and in yet an other.
If the arguments are different, you'll overload isEmpty, but, if the arguments are equal, is it right to use isEmpty, isEmpty2, isEmpty3, three classes and one isEmpty per class or, if both are wrong, what should I have done?
So the question is:
If I need different behaviors for a method isEmpty which receives the same number arguments, what should I do?
Use different names? ( isEmpty, isEmpty2, isEmpty3 )
Have three classes with a single isEmpty method?
Other?
If that's the question then I think you should use:
When they belong to the same logical unit ( they are of the same sort of validation ) but don't use numbers as version, better is to name them after what they do: isEmptyUser, isEmptyAddress, isEmptyWhatever
When the validator object could be computed in one place and passed around during the program lifecycle. Let's say: Validator v = Validator.getInstance( ... ); and then use it as : validator.isEmpty() and let polymorphism to it's job.
Alternatively you could pack the arguments in one class and pass it to the isEmpty method, although you'll end up with pretty much the same problem of the name. Still it's easier to refactor from there and have the new class doing the validation for you.
isEmpty( new Arguments(a,b,c ) ); => arguments.isEmpty();
The Open/Closed Principle [usually attributed to Bertrand Meyer] says that "software entities (classes, modules, functions, etc.) should be open for extension, but closed for modification". This might be the principle that you came across in your Java days. In real life this applies to completed code where the cost of modification, re-testing and re-certification outweighs the benefit of the simplicity gained by making a direct change.
If you are changing a method because it needs an additional argument, you might choose to use the following steps:
Copy the old method.
Remove the implementation from the copy.
Change the signature of the original method to add the new argument.
Update the implementation of the original method to use the new argument.
Implement the copy in terms of the new method with a default value for the argument.
If your implementation language doesn't support method overloading then the principle is the same but you need to find a new name for the new method signature.
The advantage of this approach is that you have added the new argument to the method, and your existing client code will continue to compile and run.
This works well if there is an obvious default for the new argument, and less well if there isn't.
Since java 5 you can use variable list of arguments as in void foo(Object ... params)
You will need to come up with creative names for your methods since you can't overload methods that have same type and number of arguments (or based on return type). I actually personally prefer this to overloading anyway. So you can have isEmpty and isEmptyWhenFoo and isEmptyWhenIHaveTheseArguments (well meybe not the last one :)
Not sure if this actually answers your question, but the best way to think about OO in "real life" is to think of the Nygaard Classification:
ObjectOrientedProgramming. A program execution is regarded as a physical model, simulating the behavior of either a real or imaginary part of the world.
So how would you build a physical device to do what you are trying to do in code? You'd probably have some kind of "Form" object, and the form object would have little tabs or bits connected to it to represent the different Form variables, and then you would build a Validator object that would take the Form object in a slot and then flash one light if the form was valid and another if it was invalid. Or your Validator could take a Form object in one slot and return a Form object out (possibly the same one), but modified in various ways (that only the Validator understood) to make it "valid". Or maybe a Validator is part of a Form, and so the Form has this Validator thingy sticking out of it...
My point is, try to imagine what such a machine would look like and how it would work. Then think of all of the parts of that machine, and make each one an object. That's how "object-oriented" things work in "real life", right?
With that said, what is meant by "extending" a class? Well, a class is a "template" for objects -- each object instance is made by building it from a class. A subclass is simply a class that "inherits" from a parent class. In Java at least, there are two kinds of inheritance: interface inheritance and implementation inheritance. In Java, you are allowed to inherit implementation (actual method code) from at most one class at a time, but you can inherit many interfaces -- which are basically just collections of attributes that someone can see from outside your class.
Additionally, a common way of thinking about OO programming is to think about "messages" instead of "method calls" (in fact, this is the original term invented by Alan Kay for Smalltalk, which was the first language to actually be called "object-oriented"). So when you send an isEmpty message to the object, how do you want it to respond? Do you want to be able to send different arguments with the isEmpty message and have it respond differently? Or do you want to send the isEmpty message to different objects and have them respond differently? Either are appropriate answers, depending on the design of your code.
Instead having one class providing multiple versions of isEmpty with differing names, try breaking down your model into a finer grained pieces the could be put together in more flexible ways.
Create an interface called Empty with
one method isEmpty(String value);
Create implemntations of this
interface like EmptyIgnoreWhiteSpace
and EmptyIgnoreZero
Create FormField
class that have validation methods
which delegate to implementations of
Empty.
Your Form object will have
instances of FormField which will
know how to validate themselves.
Now you have a lot of flexibility, you can combine your Empty implemenation classes to make new classes like EmptyIgnoreWhiteSpaceAndZero. You can use them in other places that have nothing to do with form field validation.
You don't have have have multple similarly named methods polluting your object model.

Categories

Resources