Hello!
I have been working on the problems with generics and the security model and
it's not that trivial.
The problem is this:
Let's say that in your project, you have a User class called MyUser (same
for role, permission, group). In Turbine, there are methods like
List<User> UserManager. retrieveList (Object criteria);
If we keep this method this way, you always need do cast your user class to
MyUser when you want to access methods in MyUser. In my experience, the user
class is often heavily changed and therefore a good solution here would be
valuable.
There are solutions, but implementing it is quite a bit of work, that's why
I want to discuss the solution before I begin. If anyone comes up with a
simpler solution, I would be very happy =)
To be able to have methods like:
public MyUser getUser(String username)
public boolean accountExists(MyUser user)
List<MyUser> retrieveList(Object criteria)
These steps needs to be taken:
1 Add a type parameter to the UserManager interface:
public Interfae UserManager<U>
All the methods that returned User now returns U. All the methods that took
user arguments now takes U arguments.
This also needs to be done to the implementing classes.
2 Alll the methods concerning users now needs to go through the user
manager. But this seems to have been the plan with fulcrum-security anyway.
3 We can never escape the fact that the type of the User class needs to be
defined at compile time. I'm guessing that the best solution would be that
the developer that is using turbine would instantiate their class somewhere:
UserManager<MyUser> manager = new TorqueUserManager<MyUser>();
4 Now the developer needs to be able to access the UserManager with the
specified parameter..
He can write his own access class where the the type is defined
public static UserManager<MyUser> getUserManagerInstance()
There is also a "trick" that I found in the book Effective Java by Joshua
Bloch (which I very much recommend btw).
You can create a general method that looks like this:
public <U> UserManager<U> getUserManager(Class<U> type)
I can explain the inner workings at a later stage but the point is that you
call a method where the argument is MyUser.class and you will get the
UserManager for MyUser. It's not totally magical though. Somewhere the
developer will need to instantiate his user manager by himself.
I hope you'll find some time for feedback on my research =)
/Ludwig