Varying enums in Java being accessed by common method - java

Essentially what I'm trying to do is create a generic method that can take many different kinds of enums. I'm looking for a way to do it how I'm going to describe, or any other way a person might think of.
I've got a base class, and many other classes extend off that. In each of those classes, I want to have an enum called Includes like this:
public enum Includes {
VENDOR ("Vendor"),
OFFERS_CODES ("OffersCodes"),
REMAINING_REDEMPTIONS ("RemainingRedemptions");
private String urlParam;
Includes(String urlParam) {
this.urlParam = urlParam;
}
public String getUrlParam() {
return urlParam;
}
}
I've got a method that takes in a generic class that extends from BaseClass, and I want to be able to also pass any of the includes on that class to the method, and be able to access the methods on the enum, like this:
ApiHelper.Response<Offer> offer = apiHelper.post(new Offer(), Offer.Includes.VENDOR);
public <T extends BaseClass> Response<T> post(T inputObject, Includes... includes) {
ArrayList<String> urlParams = new ArrayList<String>();
for (Include include : includes){
urlParams.add(include.getUrlParam());
}
return null;
}
Is there a way to be able to pass in all the different kinds of enums, or is there a better way to do this?
---EDIT---
I've added an interface to my enum, but how can I generify my method? I've got this:
public <T extends BaseClass> Response<T> post(Offer inputObject, BaseClass.Includes includes) {
for (Enum include : includes){
if (include instanceof Offer.Includes){
((Offer.Includes) include).getUrlParam();
}
}
return null;
}
But I get an error on apiHelper.post(new Offer(), Offer.Includes.VENDOR); saying the second param must be BaseClass.Includes.

Enums can implement interfaces, so you can create an interface with these methods that you'd like to be able to call:
interface SomeBaseClass {
String getUrlParam();
void setUrlParam(String urlParam);
}
and then your enum can implement this interface:
public enum Includes implements SomeBaseClass {
VENDOR ("Vendor"),
OFFERS_CODES ("OffersCodes"),
REMAINING_REDEMPTIONS ("RemainingRedemptions");
private String urlParam;
Includes(String urlParam) {
this.urlParam = urlParam;
}
#Override
public String getUrlParam() {
return urlParam;
}
#Override
public void setUrlParam(String urlParam) {
this.urlParam = urlParam;
}
}
If you want to get really fancy, it's possible to restrict subtypes of the interface to enums, but the generic type declaration will be pretty ugly (thus hard to understand and maintain) and probably won't provide any "real" benefits.
Unrelated note regarding this design: it's a pretty strong code smell that the enum instances are mutable. Reconsider why you need that setUrlParam() method in the first place.

Related

Java generics in List return type on a method inherited from multiple interfaces

I'm currently working at a company that has a diverse set of modules. In that company if you want to provide module internals you provide it via a java interface, that hides the actual implementing type and gives an interface for the requesting module. Now I want to have one provider to be able to provide data for multiple modules that expose different fields or methods of the actual internal data.
Therefore I have an internal Object, which has some data and I have an interface for each module that needs access to some but not strictly all fields. Finally I have an external object that implements all those interfaces and holds an instance of the internal object to delegate the method calls:
public class InternalObject {
public int getA() { return 0; }
public int getB() { return 0; }
}
public interface ModuleXObject {
int getA();
}
public interface ModuleYObject {
int getA();
int getB();
}
public class ExternalObject implements ModuleXObject, ModuleYObject {
private InternalObject _internal;
public int getA() { return _internal.getA(); }
public int getB() { return _internal.getB(); }
}
Now that is all fine and dandy, but if I want to provide - lets say - repository methods for finding a list of said objects typed for the correct module, I run into problems with how I can achieve that. I would wish for something like the following:
public interface ModuleXObjectRepository {
List<ModuleXObject> loadAllObjects();
}
public interface ModuleYObjectRepository {
List<ModuleYObject> loadAllObjects();
}
public class ExternalObjectRepository implements ModuleXObjectRepository, ModuleYObjectRepository {
public List<ExternalObject> loadAllObjects() {
// ...
}
}
This doesn't compile saying the return type is incompatible.
So my question is, if it is possible to achieve something like that and if, how?
I should note that I tried some different approaches which I want to include for completeness and to portray their downsides (in my eyes).
Approach 1:
public interface ModuleXObjectRepository {
List<? extends ModuleXObject> loadAllObjects();
}
public interface ModuleYObjectRepository {
List<? extends ModuleYObject> loadAllObjects();
}
public class ExternalObjectRepository implements ModuleXObjectRepository, ModuleYObjectRepository {
public List<ExternalObject> loadAllObjects() {
// ...
}
}
This approach is quite close to the solution I would prefer, but results in code like this:
List<? extends ModuleXObject> objects = repository.loadAllObjects();
Therefore requiring the user to include the "? extends" into each List-Declaration regarding to an invocation of loadAllObjects().
Approach 2:
public interface ModuleXObjectRepository {
List<ModuleXObject> loadAllObjects();
}
public interface ModuleYObjectRepository {
List<ModuleYObject> loadAllObjects();
}
public class ExternalObjectRepository implements ModuleXObjectRepository, ModuleYObjectRepository {
public List loadAllObjects() {
// ...
}
}
This approach just omits the generic in the ExternalObjectRepository and therefore reduces the type safety too much in my opinion. Also I haven't tested if this actually works.
Just to reharse, is there any possible way to define the loadAllObjects-method in a way that enables users to get lists that are typed with the objects for their respective module without
requiring "? extends" in the users code
degrading type safety in the repository implementation
using class/interface level generics
The challenge with allowing it to be typed as List<ModuleXObject> is that other code may hold is as a List<ExternalObject>.
All ExternalObject instances are ModuleXObject instances but the inverse is not true.
Consider the following additional class:
public class MonkeyWrench implements ModuleXObject{
//STUFF
}
MonkeyWrench instances are NOT ExternalObject instances but if one could cast a List<ExternalObject> to a List<ModuleXObject> one could add MonkeyWrench instances to this collection, and this causes a risk of run time class cast exceptions and ruins type safety.
Other code could very easily have:
for(ExternalObject externalObject:externalObjectRepository.loadAllObjects())
If one of those instances is a MonkeyWrench instance, run time class cast, which is what generics are meant to avoid.
The implication of ? extends ModuleXObject is that you can read any object from the collection as a ModuleXObject but you can't add anything to the collection as other code may have additional constraints on the collection that are not obvious/available at compile time.
I'd suggest in your case to use ? extends ModuleXObject as its semantics seem to align with what you want, namely pulling out ModuleXObject instances, e.g.
ModuleXObjectRepository repo = //get repo however
for(ModuleXObject obj : repo.loadAllObjects()){
//do stuff with obj
}

Code repetition vs readablility

I have multiple services (in Spring MVC) that are children of a global Service. So I need to know about the best practice (or your opinions) with multiple methods with this example:
//Domain classes
public class MyParentObject{}
public class MyObj extends MyParentObject{}
//Services
public class MyParentObjectServiceImpl implements MyParentObjectService{
#Override
public MyParentObject findObjectByProp(String prop, String objectType){
//myCode (not abstract class)
}
}
public class MyObjServiceImpl extends MyParentObjectServiceImpl implements MyObjectService{
private myObjType = "MyObj";
#Override
public MyObj findMyObjByProp(String prop){
return (MyObj) super.findObjectByProp(prop, this.myObjType);
}
}
And in this approach, I use calls like this:
MyObj foo = myObjService.findMyObjByProp(prop);
So I need to know if this approach is "better" or more apropiate that calling directly the parent method with the second parameter. E.g:
MyObj foo = (MyObj)myParentObjectService.findObjectByProp(prop, "MyObj");
..and avoiding the creation of second methods, more specific. It is important to know that the children services will be created anyway, because we have lot of code that is specific of a domain objects.
I have the idea that the first approach is better, because is more readable, but I need to support that decision with some documents, blog, or opinions to discuss this designs with my colleagues.
This looks like a tagged class hierarchy. It's difficult to comment on the value of this design in general without knowing the details. However, a slightly different approach that I would recommend is to generify your base class to gain a little bit of type safety.
In particular:
public /* abstract */ class MyParentObjectServiceImpl<T extends MyParentObject>
implements MyParentObjectService{
MyParentObjectServiceImpl(Class<T> type) { this.type = type; }
private final Class<T> type; // subclasses provide this
#Override
public T findObjectByProp(String prop){
//you can use type for object specific stuff
}
}
public class MyObjServiceImpl extends MyParentObjectServiceImpl<MyObj>
// You might not need this interface anymore
// if the only method defined is findMyObjByProp
/* implements MyObjectService */ {
MyObjServiceImpl() {
super(MyObj.class);
}
#Override
public /* final */ MyObj findMyObjByProp(String prop) {
return (MyObj) super.findObjectByProp(prop, this.myObjType);
}
}
You definitely gain in type safety (casting will only appear in the base class), you get rid of the "tags" (the strings that identify the different objects) and possibly reduce the number of classes/interfaces required to implement the whole hierarchy. I successfully used this approach several times. Note that this works best if the base class is abstract. Food for thoughts.

Enum static Method being called from Generic class

I want to make a refactoring and want to create a generic class for avoiding duplicate code. We have many XXXCriteriaValidator in our project and we want to make one only unique class to substitute them all.
The problem is one line where this class calls for a static method from an Enum. Here you will see. This is more or less what I'mtrying to achieve:
public class GenericCriteriaValidator<T extends ¿SomeKindOfEnumInterface?>
implements CriterionVisitor {
protected Errors errors;
public Errors getErrors() {
return this.errors;
}
/*
* Some code around here
*/
protected void doVisit(final PropertyCriterion criterion) {
if (criterion == null) {
this.errors.reject("error.criterion.null");
} else {
if (criterion.getOperator() == null) {
this.errors.reject("error.operator.null");
}
// Validates property (exception thrown if not exists)
T.fromString(criterion.getName()); // The problem is this call here!!
// Not saying this compiles, just looking
// how to do something equivalent
}
}
}
T is always a differente Enum. The typical enum is like this:
public enum ContactCriteria implements CriteriaInterface<ContactCriteria> {
// ^ This interface is added by me
// for the enum being called in the previous class
CONTACT_ID("this.id"),
CONTACT_COMPANY_ID("this.companyId"),
CONTACT_NAME("this.name"),
CONTACT_EMAIL("this.email"),
CONTACT_PHONE_NUMBER("this.phoneNumber"),
CONTACT_ORDER("this.order"),
private final String alias;
ContactCriteria(final String alias) {
this.alias = alias;
}
public String getAlias() {
return this.alias;
}
public static ContactCriteria fromString(final String name) {
ContactCriteria result = null;
if (name != null) {
result = Enum.valueOf(ContactCriteria.class, name);
}
return result;
}
public ContactCriteria returnThis() {
return this;
}
}
Finally, I'm looking for making an interface for the first class to accept the fromString method of T. I suppose it should be similar to:
public interface CriteriaInterface<T> {
static T fromString(String name);
// ^ This static is important
}
I haven't found none post or strategy for making something similar with an Enum. I know the Enum can implement an interface, but don't know how to get it.
Please help. Thanks in advance
You should start with that a static method is not allowed in Java interface.
The concept behind interfaces strongly disagree with static elements as they belong to class not to object.
So if you have a static method in a enum is just a container that is assigned to but you should not connect it by any other relations.
What is bad here is the design, you try to use enum to something that the are not dedicated on in the way you should not that why you struggle so much.
The question is if a enum instance is an CriteriaInterface then why is should provide it self by name.
Enum contains definition of "constants" that can represent an interface but can not be generic. That why enum can implement interface.
To express that you can define a interface
interface Messanger {
String getMessage();
}
And try to apply it to enum
enum Messages {
INFO
WARNING;
}
You have two options,
First, create a field that will be
enum Messages implements Messanger {
INFO,
WARNING;
private String message;
#Override
public String getMessage() {
return message;
}
}
Then you have to add the constructor to set the field
enum Messages implements Messanger {
INFO("Info"), //We create an instance of class as we call the constructor
WARNING("Warnig") //We create an instance of class as we call the constructor
;
private final String message;
public Message(String message) {
this.messsage = message;
}
#Override
public String getMessage() {
return message;
}
}
As we declare the instances inside the body of the enum you must provide all information required to create it. Assuming that enum would allow generic this is the place where you should declare it.
If the static method is on your CriteriaInterface, shouldn't you do
CriteriaIntervace.fromString("")
since static methods belong to a class (in this case CriteriaIntervace) instead of to an object?
You can't put static methods in an interface, the generics etc have no direct bearing on this. Interfaces define the methods of an instance of an object, static methods are not part of the interface of an instance, they are part of the interface of the class.
The easiest work around will be to provide a factory object to the GenericCriteriaValidator or make it abstract and provide an:
abstract T getEnum(String name);
Each implementation can then implement getEnum for the enum it is using.
Well, generally speaking, the generic type is erased and you have no other chance than explicitly telling the GenericCriteriaValidator what kind of validation logic it should apply. You might want to abstract the receiving of some type away and use a factory pattern for that what would allow you to define an interface for the fromString method.
This would result in something like this:
public interface CriteriaInterface<T> {
static class Factory<U> {
U fromString(String name);
}
}
However, I do not quite see the benefit of that in your example. Simply require an instance of CriteriaInterface<T> as a constructor argument to your GenericCriteriaValidator and define some sort of validate method in this interface.
However, if you really, really want to avoid this, there is a solution. It is possible to read the generic type of the super class of some other class (this is rather hacky, requires reflection and I would not recommend it, but some libraries love this approach). This requires you to always declare an anonymous subclass when using your generic class:
class GenericCriteriaValidator<T extends Enum<?>> implements CriterionVisitor {
private final Method criteria;
public GenericCriteriaValidator() {
ParameterizedType parameterizedType = (ParameterizedType) getClass()
.getGenericSuperclass();
try {
criteria = ((Class<?>) parameterizedType.getActualTypeArguments()[0])
.getMethod("fromString", String.class);
criteria.setAccessible(true);
} catch (NoSuchMethodException e) {
throw new IllegalArgumentException(e);
}
}
#SuppressWarning("unchecked")
private CriteriaInterface<?> invokeFromString(String value) {
try {
return (CriteriaInterface<?>) criteria.invoke(null, value);
} catch (IllegalAccessException e) {
throw new IllegalStateException(e);
} catch (InvocationTargetException e) {
throw new IllegalArgumentException(e);
}
}
// Your other code goes here.
}
Be aware that you need to instantiate your GenericCriteriaValidator as an anonymous subclass:
new GenericCriteriaValidator<ContactCriteria>() { }; // mind the braces!
As I said. I do not find this intuitive and it is most certainly not the "Java way", but you might still want to consider it.

How can you pass a List<objects that implement an interface> to a method?

I have a servlet with several methods that get a list of objects from the DAO, turn the list into JSON, and send it back in the response. Every list is made of objects that have a method:
public String getAsJson(){...}
And the servlet has a bunch of mostly identical methods that look like:
private String getUserListAsJson() {
List<User> userList = this.dao.getUsers();
StringBuilder builder = new StringBuilder();
builder.append('[');
// loops over the list appending the value of each objects getAsJson()
builder.append(']');
return builder.toString();
}
The problem is that I have about 6 methods (and growing) that look exactly like that except for different DAO queries. My idea was to create an interface that only had the definition for the getAsJson() method, make each bean implement that, and then have another method in the servlet that took objects that implemented that interface. Ended up looking like this:
public Interface JsonEnabled {
public String getAsJson();
}
public class User implements JsonEnabled {
....
#Override
public String getAsJson() {...}
}
public class TheServlet {
...
private String getUserListAsJson() {
List<User> userList = this.dao.getUsers();
return this.getListAsJson(userList);
}
private String getListAsJson(List<? implements JsonEnabled> list) {
// The loop code that is in each method.
}
}
That doesn't compile though. After looking up some documentation from Oracle, you can only have extends and not implements for generic parameters. Making all the classes extend from an Abstract Class that just has the getAsJson() method doesn't make sense semantically (the classes are unrelated).
I haven't found a good solution on SO or just googling around, so any help/insight would be appreciated.
For generic wildcards the keyword extends works for both classes and interfaces:
private String getListAsJson(List<? extends JsonEnabled> list) { ... }
extends has slightly different meaning when used for defining generic bounds - it essentially translates to "is, or extends, or implements".
Why don't just use
private String getListAsJson(List<JsonEnabled> list) { ... }
?

Can Java methods return type Enum?

I could be wrong but I'm guessing from Why can't enums be declared locally in a method?
that, since an enum in Java cannot be declared locally, that therefore it is problematic for a method to return type Enum? I can declare that a method should return an Enum (see below) but how would one then go about implementing such a method to return anything other than null, or a reference to an Enum declared outside the method? My first inclination would be to investigate using Generics for this but I'd like to avoid any deadends if the SO community can help me avoid them.
private Enum resources() {
return null;
}
I think you're correct, it's only going to be able to either return null or an Enum declared somewhere else. But you don't necessarily have to specify that "something else" at compile time.
class EnumEnumerator<T extends Enum<T>> implements Iterable<T> {
private final Class<T> enumClass;
public EnumEnumerator(Class<T> enumClass) {
this.enumClass = enumClass;
}
public Iterator<T> iterator() {
T[] values = enumClass.getEnumConstants();
return Arrays.asList(values).iterator();
}
}
Later, you invoke it by specializing the generic constructor and passing in the enum class you're interested in:
class EnumEnumeratorDemo {
enum Foo {
BAR, BAZ, QUX;
#Override public String toString() {
return name().toLowerCase();
}
}
public static void main(String[] args) {
for (Foo f : new EnumEnumerator<Foo>(Foo.class)) {
System.out.println(f);
}
}
}
(Obviously this is a contrived example and in real life you should just call Foo.values(), but you get the idea.)
The entire point of the way Java does Enums is that they are typesafe--so you wouldn't return an Enum (that would be double-plus ungood) instead you return the actual type you define (like "Suit") which acts just like a class. Suit has 4 "Enumerated" instances.
If you were expecting a "Suit", what good would it be to return a "Rank" of 7? It would break everything!
Also if you passed an "Enum" or some generic value, you couldn't call methods on it. The coolest thing about TypeSafe Enums is that you can just get a "Suit" and call "Suit.getColor()" and fully expect to get the color of that suit. You could also have a ranksHigherThan(Suit s) which might fulfill:
assertTrue(SPADES.ranksHigherThan(HEARTS));
Or, more importantly:
suit1.ranksHigherThan(suit2);
(assuming they were both passed in and you don't know what they are)
Type safety is really amazing (even though it feels a little uncomfortable at first), embrace it.
All enums implement the interface Enum, so you can certainly write a method that returns an enum this way. But this method will return a single enum value. There is no way to return a generic value which encompasses the whole enum (apart from returning the class and doing reflection). You can however return all the enum values which is more or less what you want I think.
enum Resources { ONE, TWO, THREE }
private Enum<?>[] resources() {
return Resources.values();
}
One benefit of this approach is you can return more or less values for example:
enum Resources { ONE, TWO, THREE }
enum MoreResources { UN, DEUX, TROIS }
private Enum<?>[] resources() {
List<Enum<?>> resources = new ArrayList<Enum<?>>();
resources.addAll(Arrays.asList(Resources.values());
resources.addAll(Arrays.asList(MoreResources.values());
return resources.toList(new Enum<?>[] {});
}
An even better approach that is more typesafe is to have the enums of interest
implement a common interface e.g.
public interface Resources {}
enum SomeResources implements Resources { ONE, TWO, THREE }
enum MoreResources implements Resources { UN, DEUX, TROIS }
private Resources[] resources() {
List<Resources> resources = new ArrayList<Resources>();
resources.addAll(Arrays.asList(Resources.values());
resources.addAll(Arrays.asList(MoreResources.values());
return resources.toList(new Resources[] {});
}
You can add additional methods to the interface to provide more functionality.
What are you trying to accomplish? This is a way to return an Enum:
public class Test
{
public static void main(String args[])
{
System.out.println(doit());
}
public enum Foo {
BAR,
BAZ;
}
public static Enum doit() {
return Enum.valueOf(Foo.class,"BAR");
}
}
But, I'm guessing this is not what you are going for?
Yes, it definitely is possible.
private Enum getRetentionPolicy() {
return java.lang.annotation.RetentionPolicy.SOURCE;
}
If your question is about declaring Enums, you may declare them:
in their own java file, similar to a top-level class;
within a java file belonging to another class, similar to a static inner class;
Not totally sure what your goal is, but if you wanted to return a generified method (i.e. one that would be overridden) you might have something like the following:
public class MyEnumClass<T extends Enum<T>> {
public T resources() {
//do stuff here
}
}
Not entirely sure what you would gain there, although it can be beneficial if you are talking about different sets of Enums and their elements.
If you are talking about the Enum class (i.e. the percursor to Iterator) as far as I know it has not been generified, so I am not sure generics would help much here.
You can refer to a value of an enum by its name, e.g. Suit.SPADES.
You can iterate over all values by using the values() method and pick one of the values.

Categories