How to pass enum in enum constructor ?
Here is what I tried so far.
This is to guarantee that I don't mix up pages and their respective sections.
I would like to be able to do 'SectionsEnum section = PAGE2.sectionsEnum.SECTION_D;' somewhere else in my code.
PagesEnum.class
public enum PagesEnum {
PAGE1(Page1Sections.class), // incompatible types, required SectionsEnum found Page1Sections
PAGE2(Page2Sections.class);
Class<? extends SectionsEnum> sectionsEnum;
PagesEnum(final Class<? extends SectionsEnum> sectionsEnum) {
this.sectionsEnum = sectionsEnum;
}
}
Page1Sections.enum
public enum Page1Sections implements SectionsEnum {
SECTION_A,
SECTION_B;
}
Page2Sections.enum
public enum Page2Sections implements SectionsEnum {
SECTION_C,
SECTION_D;
}
Main.class
public class Main {
public void example() {
SectionsEnum section = PAGE2.sectionsEnum.SECTION_D;
}
}
you can never get PAGE2.SECTION_D but you can do the relation other way around SECTION_D.getPage():
:
public enum SectionsEnum {
SECTION_A(PagesEnum.PAGE1),
SECTION_B(PagesEnum.PAGE1),
SECTION_C(PagesEnum.PAGE2),
SECTION_D(PagesEnum.PAGE2),
;
PagesEnum(PagesEnum page) {...}
}
Related
I have a utility class OldRemote which has been deprecated now, but still it will be used for a while till the new class NewRemote is stable. And both the utility classes has the same method names and parameters, But the return type pojo classes are different. Even return type pojo structure is same, but naming is different.
In simple, both the function return types are pojo's with different field names.
Is there any generic way to handle this below usecase ?
I have created a service interface which has the generic method contract of both old and new class.
public interface RemoteService {
//contract [ return type is object to receive all/any Pojo classes ]
Object turnOnTV();
static Service GetRemoteservice(boolean isOldRemote){
if(isOldRemote){
return new OldRemote();
}
return new NewRemote();
}
}
OldRemote Class
public class OldRemote implements RemoteService{
#Override
public OldPojo turnOnTV() {
OldPojo oldPojo = new OldPojo();
System.out.println("OldPojo");
return oldPojo;
}
}
NewRemote Class
public class NewRemote implements Service{
#Override
public NewPojo turnOnTV() {
NewPojo newPojo = new NewPojo();
System.out.println("NewPojo");
return newPojo;
}
}
Demo usage of above implementation.
public class DemoTvRemote {
public static void main(String[] args) {
RemoteService remoteService1 = RemoteService.GetRemoteservice(true);
OldPojo oldRemote = (OldPojo) remoteService1.turnOnTV();
RemoteService remoteService2 = RemoteService.GetRemoteservice(false);
NewPojo shr = (NewPojo) Service2.test();
}
}
This above code works fine. But the problem is I don't want to type cast in all the places where turnOnTV() is used in my entire code base. Even If I have to do that, I will have to write a condition to switch between OldPojo and NewPojo where ever the turnOnTV() is invoked.
Is there any way to solve this problem ?
You could create a base class or interface they both extend/implement.
public abstract class RemoteServiceBase<E> {
public abstract E turnOnTv();
}
public class NewRemoteService extends RemoteServiceBase<NewRemotePojo >{
public NewRemotePojo turnOnTv() {
return new NewRemotePojo();
}
}
public class OldRemoteService extends RemoteServiceBase<OldRemotePojo >{
public OldRemotePojo turnOnTv() {
return new OldRemotePojo();
}
}
This would still only work if you know the service type. Otherwise you work with the common generic type as one would expect.
We can deal with this with the following approach :
1) We can create a dummy POJO class in a common location with having the reference of both OldPojo and NewPojo as data members
public class CommonPojo {
OldPojo oldPojo;
NewPojo newPojo;
public void setOldPojo(OldPojo oldPojo){
this.oldPojo=oldPojo;
}
public void setNewPojo(NewPojo newPojo){
this.newPojo=newPojo;
}
public OldPojo getOldPojo(){
return oldPojo;
}
public NewPojo getNewPojo(){
return newPojo;
}
}
2)We can write a Utility method as follow which can give an object of commonpojo :
public class CommonRemote {
public static CommonPojo turnOnTv(Boolean isOldRemote){
CommonPojo commonPojo = new CommonPojo
if(isOldRemote){
OldPojo oldPojo =new OldPojo();
commonPojo.setOldPojo(oldPojo);
}else{
NewPojo newPojo =new NewPojo();
commonPojo.setNewPojo (newPojo);
}
}
}
3) Use this method as turnOnTv() as Follows :
public class DemoTvRemote {
public static void main(String[] args) {
CommonPojo remote1 = CommonRemote.turnOnTv(true);
OldPojo oldRemote = remote1.getOldPojo();
CommonPojo remote2 = CommonRemote.turnOnTv(false);
NewPojo newRemote = remote2.getNewPojo();
}
}
with this approach with little changes in code We can achieve your requirement without any typecasting.
How to choose CDI java bean base on annotation, then the annotation poses table of arguments?
The problem is easier to show using an example than to describe.
Assume that for each object of type Problem we have to choose proper solution.
public class Problem {
private Object data;
private ProblemType type;
public Object getData() { return data; }
public void setData(Object data) { this.data = data; }
public ProblemType getType() { return type; }
public void setType(ProblemType type) { this.type = type;}
}
There are few types of problems:
public enum ProblemType {
A, B, C;
}
There are few solutions:
public interface Solution {
public void resolve(Problem problem);
}
like FirstSolution:
#RequestScoped
#SolutionQualifier(problemTypes = { ProblemType.A, ProblemType.C })
public class FirstSolution implements Solution {
#Override
public void resolve(Problem problem) {
// ...
}
}
and SecondSolution:
#RequestScoped
#SolutionQualifier(problemTypes = { ProblemType.B })
public class SecondSolution implements Solution {
#Override
public void resolve(Problem problem) {
// ...
}
}
The solution should be chosen based on annotation #SolutionQualifier:
#Qualifier
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.TYPE)
public #interface SolutionQualifier {
ProblemType[] problemTypes();
public static class SolutionQualifierLiteral extends AnnotationLiteral<SolutionQualifier> implements SolutionQualifier {
private ProblemType[] problemTypes;
public SolutionQualifierLiteral(ProblemType[] problems) {
this.problemTypes = problems;
}
#Override
public ProblemType[] problemTypes() {
return problemTypes;
}
}
}
By SolutionProvider:
#RequestScoped
public class DefaultSolutionProvider implements SolutionProvider {
#Inject
#Any
private Instance<Solution> solutions;
#Override
public Instance<Solution> getSolution(Problem problem) {
/**
* Here is the problem of choosing proper solution.
* I do not know how method {#link javax.enterprise.inject.Instance#select(Annotation...)}
* works, and how it compares annotations, so I do no know what argument I should put there
* to obtain proper solution.
*/
ProblemType[] problemTypes = { problem.getType() };
return solutions.select(new SolutionQualifier.SolutionQualifierLiteral(problemTypes));
}
}
And in the last one there is a problem:
I do not know how method javax.enterprise.inject.Instance#select(Annotation...) works internally, and how it compares annotations, so I do no know what argument I should put there to obtain proper solution. If there appear a problem of type A table ProblemType[] will consist of one argument, while FirstSolution.class is annotated with #SolutionQualifier having two arguments, so therefore I will not get the proper Instance.
I didn't find a way to resolve it using CDI API, instead:
I created another enum:
public enum SoultionType {
A(ProblemType.A, ProblemType.C),
B(ProblemType.A);
//...
SoultionType(ProblemType problems...) {
// ...
}
public static SoultionType getByProblemType(ProblemType problem) {
// ...
}
}
Changed so SolutionQualifier has only SoultionType field inside, so there is no problem with the comparison.
Given the following abstract class:
public abstract class BaseVersionResponse<T extends BaseVO> {
public abstract void populate(T versionVO);
}
and the following child class:
public class VersionResponseV1 extends BaseVersionResponse<VersionVOV1>
{
protected String testFieldOne;
protected String testFieldTwo;
public String getTestFieldOne() {
return testFieldOne;
}
public void setTestFieldOne(String value) {
this.testFieldOne = value;
}
public String getTestFieldTwo() {
return testFieldTwo;
}
public void setTestFieldTwo(String value) {
this.testFieldTwo = value;
}
#Override
public void populate(VersionVOV1 versionVO) {
this.setTestFieldOne(versionVO.getFieldOne());
this.setTestFieldTwo(versionVO.getFieldTwo());
}
I desire to do something like this from a calling method:
public void getVersionInfo(String version) {
BaseVO versionVO = null;
BaseVersionResponse<? extends BaseVO> baseVersionResponse = null;
baseVersionResponse = createVersionResponse(version);
versionVO = createVersionVO(version);
baseVersionResponse.populate(versionVO);
}
where createVersionResponse(...) and createVersionVO(...) look like this:
public BaseVersionResponse<? extends BaseVO> createVersionResponse(String version) {
BaseVersionResponse<? extends BaseVO> specificVersionResponse = null;
if (version.equalsIgnoreCase("V1")) {
specificVersionResponse = new VersionResponseV1();
} else if (version.equalsIgnoreCase("V2"))
specificVersionResponse = new VersionResponseV2();
return specificVersionResponse;
}
public BaseVO createVersionVO(String version) {
BaseVO versionVO = null;
if (version.equalsIgnoreCase("V1")) {
versionVO = new VersionVOV1();
} else if (version.equalsIgnoreCase("V2"))
versionVO = new VersionVOV2();
return versionVO;
}
and VersionVOV1 looks like this:
public class VersionVOV1 extends BaseVO {
private String fieldOne = null;
private String fieldTwo = null;
private String fieldThree = null;
public String getFieldOne() {
return fieldOne;
}
public void setFieldOne(String fieldOne) {
this.fieldOne = fieldOne;
}
public String getFieldTwo() {
return fieldTwo;
}
public void setFieldTwo(String fieldTwo) {
this.fieldTwo = fieldTwo;
}
public String getFieldThree() {
return fieldThree;
}
public void setFieldThree(String fieldThree) {
this.fieldThree = fieldThree;
}
}
My problem arises when I try to compile this line of code:
baseVersionResponse.populate(versionVO);
in getVersionInfo(...). I'm getting a message that looks like this:
The method populate(capture#3-of ?) in the type BaseVersionResponse is not applicable for the arguments (BaseVO)
on the populate method above.
My thought was (which is apparently incorrect) that since the baseVersionResponse is, at this point in the code, actually a specific child instance, that the class would know exactly which populate method to call from that specific child class.
What am I doing wrong here? Is there a better way to do this if this isn't the correct approach?
Thank you for your time!
Ok, I took a better look at this today. The problem is that the wildcard, while the right way to go, precludes you from doing:
BaseVO versionVO = createVersionVO(version);
Because the populate call wants an extension of BaseVO, not an actual BaseVO, which doesn't qualify. That means you can't pass that versionVO variable directly.
So, to keep the type checking in place, which I think is good because you'll always want an implementation, leave pretty much everything as-is above, and change your BaseVersionResponse class to something like:
public abstract class BaseVersionResponse<T extends BaseVO> {
public T getVersion(BaseVO versionVO) {
try {
return (T) versionVO;
} catch (ClassCastException e) {
throw new IllegalArgumentException();
}
}
public abstract void populate(BaseVO versionVO);
}
So, populate method now takes a BaseVO, and there's a new getVersion method to do some explicit casting for us. This should be ok since we know that the factory will always supply the right thing, but if another caller doesn't, an IllegalArgumentException is thrown.
Now, in your response class implementation, change the populate method accordingly:
public void populate(BaseVO version) {
VersionVOV1 versionVO = getVersion(version);
this.setTestFieldOne(versionVO.getFieldOne());
this.setTestFieldTwo(versionVO.getFieldTwo());
}
So, we've changed the populate method to take BaseVO, and the getVersion method does the casting for us. All the other type checks still apply, and we're good to go.
The casting makes it feel not as clean, but for the factory approach you're using, it's really the only way (I can think of) to keep the guarantees made by the type declarations and the code pattern in tact.
Hope that helps!
If you just take out the capture of type (the "<?>"), and leave it unchecked, it should work just fine. Even using type Object would have compiled.
But, given your specific example, what you probably want is the method:
public BaseVersionResponse<?> createVersionResponse(String version)
Changed to:
public BaseVersionResponse<? extends BaseVO> createVersionResponse(String version)
Then, instead of using
BaseVersionResponse<?>
use
BaseVersionResponse<? extends BaseVO>
Since you know that the return type will be one of those things that implements the interface/class.
Just playing and came up with a sweet way to add functionality to enums in Java Enum toString() method with this.
Some further tinkering allowed me to nearly also add a tidy (i.e. not throwing an exception) reverse look-up but there's a problem. It's reporting:
error: valueOf(String) in X cannot implement valueOf(String) in HasValue
public enum X implements PoliteEnum, ReverseLookup {
overriding method is static
Is there a way?
The aim here is to silently add (via an interface implementation with a default method like I added politeName in the linked answer) a lookup method that does the valueOf function without throwing an exception. Is it possible? It is clearly now possible to extend enum - one of my major problems with Java until now.
Here's my failed attempt:
public interface HasName {
public String name();
}
public interface PoliteEnum extends HasName {
default String politeName() {
return name().replace("_", " ");
}
}
public interface Lookup<P, Q> {
public Q lookup(P p);
}
public interface HasValue {
HasValue valueOf(String name);
}
public interface ReverseLookup extends HasValue, Lookup<String, HasValue> {
#Override
default HasValue lookup(String from) {
try {
return valueOf(from);
} catch (IllegalArgumentException e) {
return null;
}
}
}
public enum X implements PoliteEnum/* NOT ALLOWED :( , ReverseLookup*/ {
A_For_Ism, B_For_Mutton, C_Forth_Highlanders;
}
public void test() {
// Test the politeName
for (X x : X.values()) {
System.out.println(x.politeName());
}
// ToDo: Test lookup
}
You are over-complicating your design. If you are willing to accept that you can invoke a default method on an instance only, there entire code may look like this:
interface ReverseLookupSupport<E extends Enum<E>> {
Class<E> getDeclaringClass();
default E lookup(String name) {
try {
return Enum.valueOf(getDeclaringClass(), name);
} catch(IllegalArgumentException ex) { return null; }
}
}
enum Test implements ReverseLookupSupport<Test> {
FOO, BAR
}
You can test it with:
Test foo=Test.FOO;
Test bar=foo.lookup("BAR"), baz=foo.lookup("BAZ");
System.out.println(bar+" "+baz);
An non-throwing/catching alternative would be:
interface ReverseLookupSupport<E extends Enum<E>> {
Class<E> getDeclaringClass();
default Optional<E> lookup(String name) {
return Stream.of(getDeclaringClass().getEnumConstants())
.filter(e->e.name().equals(name)).findFirst();
}
to use like:
Test foo=Test.FOO;
Test bar=foo.lookup("BAR").orElse(null), baz=foo.lookup("BAZ").orElse(null);
System.out.println(bar+" "+baz);
Here, there's basically two points. Specifically the reason it doesn't compile is 8.4.8.1:
It is a compile-time error if an instance method overrides a static method.
In other words, an enum can't implement HasValue because of the name clash.
Then there's the more general issue we have which is that static methods just cannot be 'overridden'. Since valueOf is a static method inserted by the compiler on the Enum-derived class itself, there's no way to change it. We also can't use interfaces to solve it since they do not have static methods.
In this specific case it's a place where composition can make this kind of thing less repetetive, for example:
public class ValueOfHelper<E extends Enum<E>> {
private final Map<String, E> map = new HashMap<String, E>();
public ValueOfHelper(Class<E> cls) {
for(E e : EnumSet.allOf(cls))
map.put(e.name(), e);
}
public E valueOfOrNull(String name) {
return map.get(name);
}
}
public enum Composed {
A, B, C;
private static final ValueOfHelper<Composed> HELPER = (
new ValueOfHelper<Composed>(Composed.class)
);
public static Composed valueOfOrNull(String name) {
return HELPER.valueOfOrNull(name);
}
}
(Plus, I'd recommend that over catching the exception anyway.)
I realize "you can't do it" is not really a desirable answer but I don't see a way around it due to the static aspect.
The case is the same as you can not create default toString() in interface. The enum already contains signature for static valueOf(String) method therefore you can not override it.
The enum are compile time constant and because of that it really doubtful that they will be extensible someday.
If you want to get the constant via name you can use this:
public static <E extends Enum<E>> Optional<E> valueFor(Class<E> type, String name) {
return Arrays.stream(type.getEnumConstants()).filter( x -> x.name().equals(name)).findFirst();
}
I think I have an answer - it's hacky and uses reflection but seems to fit the brief - i.e. reverse lookup without methods in the enum and without throwing exception.
public interface HasName {
public String name();
}
public interface PoliteEnum extends HasName {
default String politeName() {
return name().replace("_", " ");
}
}
public interface Lookup<P, Q> {
public Q lookup(P p);
}
public interface ReverseLookup<T extends Enum<T>> extends Lookup<String, T> {
#Override
default T lookup(String s) {
return (T) useMap(this, s);
}
}
// Probably do somethiong better than this in the final version.
static final Map<String, Enum> theMap = new HashMap<>();
static Enum useMap(Object o, String s) {
if (theMap.isEmpty()) {
try {
// Yukk!!
Enum it = (Enum)o;
Class c = it.getDeclaringClass();
// Reflect to call the static method.
Method method = c.getMethod("values");
// Yukk!!
Enum[] enums = (Enum[])method.invoke(null);
// Walk the enums.
for ( Enum e : enums) {
theMap.put(e.name(), e);
}
} catch (Exception ex) {
// Ewwww
}
}
return theMap.get(s);
}
public enum X implements PoliteEnum, ReverseLookup<X> {
A_For_Ism,
B_For_Mutton,
C_Forth_Highlanders;
}
public void test() {
for (X x : X.values()) {
System.out.println(x.politeName());
}
for (X x : X.values()) {
System.out.println(x.lookup(x.name()));
}
}
prints
A For Ism
B For Mutton
C Forth Highlanders
A_For_Ism
B_For_Mutton
C_Forth_Highlanders
Added
Inspired by #Holger - this is what I feel is most like what I was looking for:
public interface ReverseLookup<E extends Enum<E>> extends Lookup<String, E> {
// Map of all classes that have lookups.
Map<Class, Map<String, Enum>> lookups = new ConcurrentHashMap<>();
// What I need from the Enum.
Class<E> getDeclaringClass();
#Override
default E lookup(String name) throws InterruptedException, ExecutionException {
// What class.
Class<E> c = getDeclaringClass();
// Get the map.
final Map<String, Enum> lookup = lookups.computeIfAbsent(c,
k -> Stream.of(c.getEnumConstants())
// Roll each enum into the lookup.
.collect(Collectors.toMap(Enum::name, Function.identity())));
// Look it up.
return c.cast(lookup.get(name));
}
}
// Use the above interfaces to add to the enum.
public enum X implements PoliteName, ReverseLookup<X> {
A_For_Ism,
B_For_Mutton,
C_Forth_Highlanders;
}
I have an interface which multiple enums are implementing, i.e
public interface MinorCodes {
public abstract int code();
public abstract String description();
}
public enum IdentityMinorCodes implements MinorCodes {
IDENTITY_UPLOAD_PICTURE_CODE(1, "Error while trying to upload a picture."),
}
Now I want to have a custom annotation which has a value type of one of these concrete enum values, i.e
public #interface PokenService {
MinorCodes[] exceptions();
}
But of course I cannot return an interface here.
Does anyone know any solution or workaround to this?
Thanks in advance.
You could create an additional enum that wraps all your MinorCodes enum values:
public enum MinorCodesWrapper {
IDENTITY_UPLOAD_PICTURE_CODE(IdentityMinorCodes.IDENTITY_UPLOAD_PICTURE_CODE),
SOME_CODE(AnotherMinorCodes.SOME_CODE);
private final MinorCodes _wrapped;
MinorCodesWrapper(MinorCodes wrapped) {
_wrapped = wrapped;
}
public MinorCodes getWrapped() {
return _wrapped;
}
}
public #interface PokenService {
MinorCodesWrapper[] exceptions();
}
Not pretty, but works ;)