'Wildcard' Importing for Interface - java

I'm looking to create an interface for my plugin which uses a different class depending on the servers version.
I've tried to include the following in my interface class:
Map<String, EntityPlayer> getPlayers();
However 'EntityPlayer' is imported depending on version, and so it's not viable for me to do this. I essentially need it to be a 'wildcard', where it can be any EntityPlayer import. Then in classes where my interface is implemented, I can use the per-version import.
Hopefully this clarifies what I'm trying to accomplish and what I have done so far.
Thanks all.

You can use a generic Interface something like this
interface YourInterface<T> {
Map<String, T> getPlayers();
}
you could also use a more specific constraint if EntityPlayer is derived from a parent class e.g
interface YourInterface<T extends EntityParentClass> {
Map<String, T> getPlayers();
}

Related

Using Reflections.getSubTypeOf() to get subtypes of Parameterized interface

I'm trying to extract all classes that implement an interface and put these in a Set.
However, that interface is Parameterized and I'd like to communicate that it's
all subclasses, regardless of their "parameter" I want, using a wildcard or something like that.
However, I still need access to that parameter when going through the Set.
(Btw I'm using the Reflections library)
The interface I'm trying to get subclasses of:
public interface Shouter<T> {
void shout(T dataObj);
}
What I'm trying to do (which I can't get to work)
private static Set<Class<? extends Shouter<?>>> extractShouters(String rootPackage) {
Reflections reflections = new Reflections(rootPackage);
return (Set<Class<? extends Shouter<?>>>) reflections.getSubTypesOf(Shouter<?>.class);
}
I'm getting an error in the last bit there, the "Shouter<?>.class", and I know that what I've written wont compile but I don't know how else.
Now, I'm relatively new to Reflections, so I don't know if just addressing it as RAW would solve it and still give me access to the parameter.
The Set I mentioned earlier:
private Set<Class<? extends Listening<?>>> listeners;
private Set<Class<? extends Shouter<?>>> shouters;

Get all classes within constrains

Im trying to make a generic instance mapper from an SQLite DB to my project logic layer.
Each entry in the mapper is an instance of some class "DAL< name >" for example DALProduct all in the same package that extends class DALObject with the following structure:
public abstract class DALObject{
abstract String getCreate();
... //other logic
}
Using reflection I can easily call the getCreate method on each class and get what I need from it.
The issue is that I don't know how many child classes DALObject will have and i want a mapper that won't need to be touched when a new one is added.
I know that you can get all child classes of DALObjects that have been loaded but I run this code at the very start of my program before I load any of the classes.
Any ideas? I have a pretty big constraint case so maybe I can somehow hack it together.
Such task is only possible by scanning every class on the classpath (which, depending on how many libraries you use, are usually a lot) and see if it extends DALObject.
If you want to go that route, the org.reflections library can help you with that:
Reflections reflections = new Reflections("my.package",
Reflector.class.getClassLoader(), new SubTypesScanner(false));
Set<Class<? extends Module>> modules = reflections.getSubTypesOf(DALObject.class);
For performance reasons, I highly recommend doing this scan once during startup of your application and store the results.
As an alternative approach (I did not bother with generic type safety of Class here, this is to be implemented):
public abstract class DALObject {
public static List<Class> subTypes = new ArrayList<>();
public DALObject() {
DALObject.subTypes.add(this.getClass());
}
}
Obviously this only works if you instantiate objects of the subclasses somewhere, if your getCreate is meant to do that in the first place, my suggestion will obviously not work.
This would be a perfect instance of when to use an annotation. You could define the annotation before the declaration of each class, indicating that the class has some meta-data about 'DALObjects'. Then you could use Reflections or some similar library to easily find all Class objects with this annotation.
For example;
#Target(value=TYPE)
public #interface DALObject {
}
#DALObject
public class MyDALObject {
}
Reflections reflections = new Reflections(new ConfigurationBuilder()
.setScanners(new TypeAnnotationsScanner()));
Set<Class<?>> annotatedWithDALObject = reflections.getTypesAnnotatedWith(DALObject.class);
Last I know, Reflections isn't well supported (only minor changes in years) and still doesn't work with modules.
Instead, I'd recommend using ClassGraph, which is ultra-actively maintained, and works with modules, weird class loaders and what not.
You'd find DALObject implementations like this:
ScanResult scanResults = new ClassGraph()
.acceptPackages(packages) //skip to scan ALL packages
.enableAllInfo() //Not necessary but gives you more info to filter on, if needed
.initializeLoadedClasses()
.scan();
//You can cache, or serialize scanResults using scanResults.toJSON()
List<Class<?>> impls = scanResults.getAllClasses().stream()
.filter(impl -> impl.extendsSuperclass(DALObject.getName()))
// or impl.implementsInterface(DALObject.getName()) if DALObject is an interface
.flatMap(info -> info.loadClass()) //or load the class yourself if you need to customize the logic
.collect(Collectors.toList());

Jackson ObjectMapper only interfaces known

If I want to read some JSON into an object, and I have the interface but must use the Spring context to get the implementation class, I need to use a SimpleAbstractTypeResolver to map the interface to the implementation. So far, so good, if I know in advance what interfaces go to what implementation. But if the interface has methods that return other interfaces--and possibly down the line recursively--and I don't necessarily know in advance, I thought I could use reflection to figure it out. So this is what I came up with, but the compiler does NOT like the line resolver.addMapping(method.getReturnType(), method.getReturnType());, says it's not applicable for these arguments. I'm pretty sure the types are okay for that method--any thoughts on how to make this happen?
for (Method method : clazz.getMethods()) {
if (method.getReturnType().isInterface() && method.getName().startsWith("get")) {
// getter method returns an interface so find its implementation class
Class beanClass = context.getBean(method.getReturnType()).getClass();
if (clazz.isAssignableFrom(beanClass)) {
resolver.addMapping(method.getReturnType(), method.getReturnType());
mapInterfaces(objectMapper, clazz, resolver);
}
}
}
Probably you need to review your types.
My guess is following:
resolver.addMapping(method.getReturnType(), beanClass);
(replace second parameter method.getReturnType() with beanClass)
or as an alternative (the code is not completely clear for me, sorry)
resolver.addMapping(clazz, beanClass);
You should put an Interface and Implementation into addMapping().
Example:
interface ITest{};
class TestImpl implements ITest {}
usage:
resolver.addMapping(ITest.class, TestImpl.class);
Probably you need to review your types.
My guess is following:
new ObjectMapper().writerFor(<Interface>.class).writeValuesAsArray(<Class>);

Guice equivalent of Spring's #Autowire list of instances

In spring when I do:
#Autowire
List<MyInterface> myInterfaces;
then this list will get populated by all beans which implement MyInterface. I didn't have to create bean of type List<MyInterface>.
I'm looking for such behaviour in Google Guice.
Sofar I went with:
Multibinder<MyInterface> myInterfaceBinder = MultiBinder.newSetBinder(binder(), MyInterface.class);
Now if I have a bean which implements MyInterface and I bind it, say via:
bind(MyInterfaceImpl.class).asEagerSingleton();
it won't be included in my multibinder. I need to add:
myInterfaceBinder.addBinding.to(MyInterfaceImpl.class);
This is somewhat more complicated than what Spring offers. So I was wonmdering whether I'm not using it in wrong way. So is there easier way of achieving this?
I haven't used it that way myself, yet, but according to Guice's API documentation, I think you should be able to write something not much more than this once:
bindListener(Matchers.subclassesOf(MyInterface.class), new TypeListener() {
public <I> void hear(TypeLiteral<I> typeLiteral,
TypeEncounter<I> typeEncounter) {
myInterfaceBinder.addBinding().to(typeLiteral);
}
}
Then, when you bind an implementation via
bind(MyInterfaceImpl.class).asEagerSingleton();
it should be added to your multibinder automatically.
A hacky solution would be to do it all in a loop:
Multibinder<MyInterface> myInterfaceBinder
= MultiBinder.newSetBinder(binder(), MyInterface.class);
Class<? extends MyInterface>[] classes = {
MyInterfaceImpl,
YourInterfaceImpl.class,
MyCatsInterfaceImpl
};
for (Class<? extends MyInterface> c : classes) {
bind(c).asEagerSingleton();
myInterfaceBinder.addBinding.to(c);
}
It's hacky, it's applicable for such simple cases only, but it's simple and DRY.

Is there wildcard for annotatted classes

Persistent object:
#Entity
public class PersistentModelObject{
...
}
I need something like:
interface GenericDao<T annotated_with Entity>{
//crud
}
Or can it be simulated in some way (with extension, implementation, etc).
EDIT: Please someone who understands my question to edit it to some understandable level.
I dont think you can use annotations like that via generics, but you can use java.lang.Class java.lang.reflect.Field isAnnotationPresent(YourAnnotation.class) to check if a class is annotated with a certain annotation.
A better aproach might be using marker interfaces? Something like:
public class PersistentModelObject implements MyPersistableType{
...
}
and
interface MyPersistableType {} //marker interface
Then you may use it like this:
interface GenericDao<T extends MyPersistableType>{
//crud
}
But then again, it depends on what you are trying to solve.
This restriction can only be checked at runtime using reflection.

Categories

Resources