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.
Related
Context
I am working with very similar classes like RechargeResponse or ConsultResponse. All of them (around 80) are generated from WSDL scheme has the same structure. (This scheme comes from 3PP company, so I can't change this logic.)
Each of them contains inner classes: RechargeResult and ConsultResult.
I have a bunch of methods with same functionality. The only difference is that I need to call (for example) response.get_ClassName_Result().getAny() to check data.
Question
How can I escape from using in every method same code with only ClassNameMethod changed?
Is any solution like Generics, Reflections or some else could be used? (I think parsing classname like string is not a solution).
Code examples below:
Similar classes:
public class ConsultResponse {
protected ConsultResult consultResult;
public ConsultResult getConsultResult() {
return consultResult;
}
public static class ConsultResult {
protected Object any;
public Object getAny() {
return any;
}
public void setAny(Object value) {
this.any = value;
}
}
}
public class RechargeResponse {
protected RechargeResult rechargeResult;
public RechargeResult getRechargeResult() {
return rechargeResult;
}
public static class RechargeResult {
protected Object any;
public Object getAny() {
return any;
}
public void setAny(Object value) {
this.any = value;
}
}
}
Similar (duplicated) method for each class:
private void validateConsult(ConsultResponse response) {
if (response == null ||
response.getConsultResult() == null || // need solution here
response.getConsultResult().getAny() == null) { // need solution or change here
throw new Exception();
}
}
One of the problems is that your get«classname»Result method names include the class names. That makes it impossible to make it generic without using reflection. Why don't you just rename both to getResult? You could then use generics to make the class generic.
First, we define an interface which defines both getAny and setAny.
public interface Result {
Object getAny();
void setAny(Object value);
}
Then we could create an implementation of Result, which is, for example, ConsultResult. You could do the same with RechargeResult.
public class ConsultResult implements Result {
protected Object any; // You already have a getter, so this can also be private
public Object getAny() {
return this.any;
}
public void setAny(Object value) {
this.any = value;
}
}
Then we could create a base class Response, which defines the getResult method. The class accepts a type argument T which must implement Result.
public abstract class Response<T extends Result> {
protected T result; // You already have a getter, so this can also be private
public T getResult() {
return this.result;
}
}
At last, we also create our ConsultResponse class. We extend it from Response, and we provide as type argument ConsultResult.
public class ConsultResponse extends Response<ConsultResult> {
// The field 'result' is already present within the Response class,
// so there is no need to include it here.
}
Also, as GhostCat already said in the comments: what is the point of having two different inner classes in the first place? They're both the same in your example as it is currently written. You could replace them with a single base class; however, it could be that there's more members within those classes which are not shown in your example, so I left them as they were in my example.
For the validation you could do roughly the same.
There are several ways around it, for example by creating a superclass from which ConsultResponse and RechargeResponse would be extending. The superclass would have the shared method defined, so you don't have to define it in the extended classes, unless you'd want to override it.
Another approach would be to separate the validation completely into a separate class, for example a ResponseValidator which would handle the validation on its own and would be included and used in the ConsultResponse and RechargeResponse classes.
It's hard to pinpoint an exact solution to this because it depends on your specific situation which we are not aware of completely.
In a Java application I'm working on, I have a number of enums which ended up having a static fromString method in them for converting a string to its actual enum value.
So, I thought I could have a "base" class from which all my enums can extend without have to repeat that code all the time. Since enums cannot extend classes, I've planned to do is that I might be able to do that through an interface instead.
What I've is the following:
public interface IBaseEnum {
String enumVal = null;
public static <T extends Enum<T> & IBaseEnum> Enum<T> fromString(String strVal) {
if (strVal == null) return null;
// T.values() has error because T is not recognised to have the method values()
for (T myEnum : T.values()) {
if (myEnum.enumVal.equals(strVal.toUpperCase())) {
return myEnum;
}
}
return null;
}
}
And then, to inherit that static method, I will implement IBaseEnum in my actual Enum:
public enum Colour implements IBaseEnum {
Red("red");
//...
}
However, I'm having issues with the types in IBaseEnum. The line T.values() is having error because the generic type T cannot be referenced back to the enum itself and so it is complaining that the method values() is not found.
Is this the right way to inherit functionalities in enum? Otherwise, how can I inherit methods in enums so that I don't have to copy/paste and repeat a same set of methods in every single enums?
There are a few reasons why your code would not work, of which I should mention:
String enumVal = null;: IBaseEnum being an interface, numVal gets the implicit public, static, and final modifiers. However, you intend enumVal to be an instance property.
T.values(): of course this doesn't compile. But even if it could (or you had the class instance), you still wouldn't be able to make this dynamic. Static methods are picked at compile time. The only way (that I know) to make it work dynamically would be to use reflection, of course passing in the class object of the enum.
Because you want to be able to call Color.fromString(...), you have no choice but to declare this as a static method in each enum class. With that said, I think the most you can reuse from your logic is the lookup code (again, that's unless you use reflection).
To reuse the lookup logic, you can change the contract of IBaseEnum to make it declare a method that that returns the enumVal value. Beside that, the values() method can be invoked by the enum classes themselves. Here's what it can look like:
interface IBaseEnum {
String enumVal();
public static <T extends Enum<T> & IBaseEnum> T
fromString(String strVal, T[] values) {
if (strVal == null)
return null;
for (T myEnum : values) {
if (myEnum.enumVal().equalsIgnoreCase(strVal)) {
return myEnum;
}
}
return null;
}
}
And that will lead to an enum class like the following:
enum Colour implements IBaseEnum {
VAL1("string")
;
private final String val;
Colour(String v) {
this.val = v;
}
#Override
public String enumVal() {
return this.val;
}
public static Colour fromString(String s) {
return IBaseEnum.fromString(s, values());
}
}
Remember: if enumVal() is intended to return just the enum literal, then you can get rid of all this complexity by just using the valueOf method available in all enums. Only do this if the comparison of your values needs custom logic.
I have two classes CashStore and DrinkStore, both extends from Store. I have a StoreFactory class (returns Store object) to instantiate objects for clients. I want to access methods specific to child classes from these clients. How do I do it without casting? If I used casting, would it break the pattern, since now the clients know about the Child classes?
class Store{
A(){}
B(){}
}
class CashStore{
A(){}
B(){}
C(){}
D(){}
}
//impl for drink store and other stores
class StoreFactory{
public Store getStore(String type){
//return a Store obj based on type DrinkStore or CashStore
}
}
class Client{
StoreFactory fac;
public Client(){
fac = new StoreFactory();
Store s = fac.getStore("cash");
s.C(); //requires a cast
}
}
Does casting break my pattern?
Factory pattern is used to decouple from runtime type. For example, when it's platform- or layout-specific, and you don't want your client code to mess with it. In your case you do need an exact type, so it seems factory pattern isn't a good choice. Consider using simple static methods, like:
class Stores {
static CashStore createCashStore() {
return new CashStore();
}
static DrinkStore createDrinkStore() {
return new DrinkStore();
}
}
So basically you need to access child specific methods without casting. That's the whole purpose of Visitor pattern.
You can switch between different child by using method overloading. I have given an example below, you would need to adapt that to fit into your code. And also you should take out the business logic from the constructor (of Client) and implement them inside methods.
public class Client{
public void doSomething(CashStore cs){
cs.c();
//you can call methods specific to CashStore.
}
public void doSomething(DrinkStore ds){
ds.e();
//you can call methods specific to DrinkStore.
}
}
I want to access methods specific to child classes from these clients.
How do I do it without casting?
If you know the expected type, then you can use generics to avoid casting:
interface Store {
}
class WhiskeyStore implements Store {
}
class VodkaStore implements Store {
}
class StoreFactory {
<T extends Store> T getStore(Class<T> clazz) {
try {
// I use reflection just as an example, you can use whatever you want
return clazz.getConstructor().newInstance();
} catch (Exception e) {
throw new RuntimeException("Cannot create store of type: " + clazz, e);
}
}
}
public final class Example {
public static void main(String[] args) {
WhiskeyStore whiskeyStore = new StoreFactory().getStore(WhiskeyStore.class);
VodkaStore vodkaStore = new StoreFactory().getStore(VodkaStore.class);
}
}
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.
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.