Java Interface containing an empty Enum - java

I'm trying to prepare an interface i want to implement for Datamodel-Classes.Therefor i want to use an enum inside the interface so i know i need to implement it later.
Example:
public interface MyModelInterface {
public enum Field;
public Object get(Field field);
public void set(Field field, Object value);
}
The expected implementation:
public class MyModel implements MyModelInterface {
public enum Field {
ID("id"),
Name1("Name1"),
Name2("Name2");
private String field;
private Field(String field) {
this.field = field;
}
}
public Object get(Field field) {
//...
}
public void set(Field field, Object value){
//...
}
public static void main(String[] args) {
MyModel myModel = new MyModel();
System.out.println(myModel.get(MyModel.Field.ID));
System.out.println(myModel.get(MyModel.Field.Name1));
}
}
Since I don't know which fields the model will contain until I implement it.
I did some research and figured that enum can't be extended, so i am aware of that.
is there any way to archive this or any kind of workaround?
i don't want to use String Parameters on the getter/setter Methods to avoid using wrong values.
Thanks in advance for any suggestion.
Update:
So this is what worked for me: Splitting the interface/class in three parts, including an abstract class:
Interface:
public interface MyModelInterface<E extends Enum<E>> {
public Object get(E field);
public void set(E field, Object value);
}
Abstract Class:
public abstract class MyAbstractModel<E extends Enum<E>> implements MyModelInterface<E>{
protected final EnumMap<E, Object> fields;
public MyAbstractModel(Class<E> enumKlazz) {
fields = new EnumMap<>(enumKlazz);
}
#Override
public Object get(E field) {
return fields.get(field);
}
#Override
public void set(E field, Object value) {
this.fields.put(field, value);
}
}
Class(where i actually archive my goal):
public class MyModel extends MyAbstractModel<MyModel.Field> {
public MyModel() {
super(MyModel.Field.class);
}
public enum Field {
ID("ID"),
Name1("NAME1"),
Name2("NAME2"),
Age("AGE"),
;
private final String field;
private Field(String field) {
this.field = field;
}
public String getName() {
return field;
}
}
public static void main(String[] args) {
MyModel myModel = new MyModel();
System.out.println(myModel.get(Field.Name1));
}
}

Interface fields are static and final implicitly.
What you could do is to have an interface method returning Enum<?>, and your classes implementing it.
For instance:
interface Foo {
public Enum<?> getEnum();
}
class Bar implements Foo {
enum Blah {
INSTANCE;
}
public Enum<?> getEnum() {
return Blah.INSTANCE;
}
}
Edit
Not completely sure I understand your question update, but here's a solution that will de-couple returning a specific enum instance from an enum, by means of two interfaces.
The example is self-contained in a Main class.
public class Main {
public static void main(String[] args) {
System.out.println(new Bar().getEnumField().name());
}
static interface IHasEnum {
public Enum<? extends IMyEnum> getEnumField();
}
static interface IMyEnum {
public Enum<? extends IMyEnum> getField();
}
static class Bar implements IHasEnum {
enum Blah implements IMyEnum {
DEFAULT_INSTANCE,
THE_FIELD;
public Enum<? extends IMyEnum> getField() {
return THE_FIELD;
}
}
public Enum<? extends IMyEnum> getEnumField() {
return Blah.DEFAULT_INSTANCE.getField();
}
}
}
Output
THE_FIELD
Note
The trick here is to add a "default" instance to the enum (DEFAULT_INSTANCE), so the getField method is an instance method, hence overriding the one declared in the IMyEnum interface.
Again, not entirely sure this addresses your issue.

What you are describing is an EnumMap<E, T> - which functions like an array, with that same get-
public class MyModelBase<E extends Enum<E>> {
private final Class<E> enumKlazz;
private final EnumMap<E, Object> fields;
public MyModelBase(Class<E> enumKlazz) {
this.enumKlazz = enumKlazz;
fields = new EnumMpa<>(enumKlazz);
}
public Object get(E field) {
return fields.get(field);
}
public void set(E field, Object value) {
fields.put(field, value);
}
}
enum UserField { id, surname, name, age };
MyModelBase<UserField> userModel = new MyModelBase<>(UserField.class);
userModel.set(UserField.surname, "X");
Because of type erasure the enum map needs the class. Above the enum class is also stored as field, as some static Enum methods need the enum class. For iterating, and so on.

Java generics will be the best solution.
Lets assume, you don't know the contents of the Field as mentioned.
Create a generic interface like this:
public interface MyModelInterface<T> {
public T get();
}
Then create a class Field like this:
public class Field {
private String id;
private String name1;
private String name2;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName1() {
return name1;
}
public void setName1(String name1) {
this.name1 = name1;
}
public String getName2() {
return name2;
}
public void setName2(String name2) {
this.name2 = name2;
}
}
and then your model class will look like
public class MyModel implements MyModelInterface<Field> {
#Override
public Field get() {
Field field = new Field();
field.setId("ID");
field.setName1("Name1");
field.setName2("Name2");
return field;
}
public static void main(String[] args) {
MyModel myModel = new MyModel();
System.out.println(myModel.get().getId());
System.out.println(myModel.get().getName1());
System.out.println(myModel.get().getName2());
}
}

Related

Create a generic method with generic signature

i have some redundant code that i would like to remove, my goal would be to create a method of this kind:
private GenericClass myMethod(GenericClass genericClass){
genericClass.getTipe(); //tipe1 or tipe2
genericClass.setValue("foo");
genericClass.setValue2("foo");
//some logic
return genericClass;
}
Where this method can pass two similar classes but which differ in the type of an attribute
public class Class1{
private Tipe1 tipe1;
private String value;
private String value2;
//Constructor,Getter and Setter
}
public class Class2{
private Tipe2 tipe2;
private String value;
private String value2;
//Constructor,Getter and Setter
}
What I would like to do is call the method
someServiceIml.myMethod ("Foo")
passing either an object of type Class1 or Class2 according to my needs, the business logic behind myMethod is practically the same.
This method i wish it was in the same implementation of a certain service, could you give me some solution?
Create a generic abstract type; either a super class or an interface:
public interface GenericClass<T> {
public T getTipe();
public void setValue(String s);
public void setValue2(String s);
}
Have your implementation classes implement it:
public class Class1 implements GenericClass<Tipe1> {
// leave implementation as is
}
public class Class2 implements GenericClass<Tipe2> {
// leave implementation as is
}
And type your method:
private <T> GenericClass<T> myMethod(GenericClass<T> genericClass){
T tipe = genericClass.getTipe();
genericClass.setValue("foo");
genericClass.setValue2("foo");
// some logic
return genericClass;
}
If Tipe1 and Tipe2 share a common type, you can type them too:
public interface GenericClass<T extends SomeTipe> {
public class MyClass {
public static void main(String args[]) {
Class1 c1 = new Class1();
Class2 c2 = new Class2();
GenericClass gc = myMethod(c1);
System.out.println(gc);
}
private static GenericClass myMethod(GenericClass genericClass){
genericClass.getTipe(); //tipe1 or tipe2
genericClass.setValue("foo");
genericClass.setValue2("foo");
//some logic
return genericClass;
}
}
class Class1 extends GenericClass<Tipe1>{
}
class Class2 extends GenericClass<Tipe2>{
}
class Tipe1 {
}
class Tipe2 {
}
class GenericClass<T> implements Tipe<T> {
private String value;
private String value2;
private T t;
public T getTipe() {
return t;
}
void setValue(String s) {
value = s;
}
void setValue2(String s) {
value2 = s;
}
}
interface Tipe<T> {
public T getTipe();
}
or you can cast to parent class like:
GenericClass gc = new Class2();

Casting from Non-generic base class to Generic Sub class

I have non-generic parent class.
public class FilterCondition {
private String key;
private String value;
private String condition;
}
And I have a generic subclass.
public class FilterJoinCondition<P,S> extends FilterCondition {
public FilterJoinCondition(String key, String value, String condition) {
super(key, value, condition);
}
private Class primaryEntity;
private Class secondaryEntity;
private String mappedBy;
}
I store all the FilterCondition in a List and pass to a method where I need the types passed to the FilterJoinCondition
if (condition instanceof FilterJoinCondition) {
FilterJoinCondition<P,S> joinCondition = (FilterJoinCondition) condition;
}
I know this is not correct (above code).
How could I cast FilterCondition without knowing the types (P,S) ?
You can just use the ? placeholder. Obviously you won't be able to do things with the new joinCondition, that requires knowledge of the specific Types. But all the general stuff you can do just fine.
public class FilterJoinCondition<P,S> extends FilterCondition {
private Class primaryEntity;
private Class secondaryEntity;
private String mappedBy;
public FilterJoinCondition(String key, String value, String condition) {
super(key, value, condition);
}
public void doStuff(P param) {
System.out.println(param.getClass());
}
public static void main(String[] args) {
FilterCondition condition = new FilterJoinCondition<>("foo", "bar", "baz");
if (condition instanceof FilterJoinCondition) {
FilterJoinCondition<?,?> joinCondition = (FilterJoinCondition) condition;
joinCondition.doStuff(new String()); //illegal, you do not know P!
}
}
}

Java: Calling a parent's method with child's member variable

Let's say I have an abstract parent class that has member variables which are used in a method.
public abstract class Person{
public String jobTitle;
public void printJob(){
System.out.println(jobTitle);
}
}
If I now have two child classes
public class Teacher extends Person{
public String jobTitle = "Teacher";
}
public class Janitor extends Person{
public String jobTitle = "Janitor";
}
and I want to avoid code cloning, i.e. implementing the same printJob()-method in both classes, I now have a problem, since the printJob()-method is unable to access member variables of the child classes.
Is there any way that i can call a parent classes' method but have the method use the child classes' member variables?
You can use abstract methods like this
public abstract class Person {
public void printJob() {
System.out.println(getJobTitle());
}
protected abstract String getJobTitle();
public static void main(String[] args) {
Person teacher = new Teacher();
Person janitor = new Janitor();
System.out.println(teacher.getJobTitle());
System.out.println(janitor.getJobTitle());
}
}
class Teacher extends Person {
#Override
protected String getJobTitle() {
return "Teacher";
}
}
class Janitor extends Person {
#Override
protected String getJobTitle() {
return "Janitor";
}
}
Updated after op's comment for code cloning...
public class Person {
public static void main(String[] args) {
System.out.println(new Teacher().job);
System.out.println(new Janitor().job);
}
private static class Teacher extends Person {
private String job = "Teacher";
}
private static class Janitor extends Person {
private String job = "Janitor";
}
}

Easy access Object Getter with Java

Method 1: traditional getter/setter
Toyota class:
public class ToyotaCar implements Serializable {
private static final long serialVersionUID = 2011932556974180375L;
private int miles;
public void addMiles(int miles){
this.miles = miles;
}
public int getMiles(){
return miles;
}
}
Human class:
public class Human implements Serializable {
private static final long serialVersionUID = 1748193556974180375L;
private ToyotaCar car;
public void setCar(ToyotaCar car){
this.car = car;
}
public int getCar(){
return car;
}
public void addCarMiles(int num){
getCar().addMiles(num);
}
}
Method 2: "other"
Toyota class: -same as above toyota class-
Additional containerHandler class:
public enum HumanContentsContainer {
CAR{
#Override public Object getContainer(){
return new ToyotaCar();
}
},
HOUSE;
public Object getContainer(){ //because cannot be static enum constant as every human has different items
return null;
}
}
Human class:
public class Human implements Serializable {
private static final long serialVersionUID = 1748193556974180375L;
private HashMap<HumanContentsContainer, Object> contents;
public void setContents(){
for (HumanContentsContainer c : HumanContentsContainer.values()){
contents.put(c, c.getContainer());
}
}
public HashMap<HumanContentsContainer, Object> getContents(){
return contents;
}
public void addCarMiles(int num){
//TODO how to replicate this: getCar().addMiles(num);???
}
//TODO i dont want to use the below method because whats the point of creating a whole container handler if im just going to use a traditional getter again?
//public ToyotaCar getCar(){
// return (ToyotaCar) contents.get(HumanContentsContainer.CAR);
// }
}
So how do I replicate the getCar().addMiles(x) method using a traditional getter without actually creating a getter?
Please note I also don't want to do this (below code): Because again, not worth it over a getter then:
public void addCarMiles(int num){
((ToytotaCar)contents.get(HumanContentsContainer.CAR).addMiles(num);
}
Looking for some easy kind of usage like:
human.getContentsThatIsIntanceOf(ToyotaCar).addMiles(1);
But don't know what getContentsThatIsInstanceOf would look like
I would go with:
public class Human implements Serializable {
private static final long serialVersionUID = 1748193556974180375L;
private ToyotaCar car;
public void setCar(ToyotaCar car){
this.car = car;
}
public int getCar(){
return car;
}
public void addCarMiles(int num){
getCar().addMiles(num);
}
public Map<HumanContentsContainer, Object> getContents(){
Map<HumanContentsContainer, Object>map = new HashMap();
map.put(CAR,this.car );
//same for all the shoes and clothes and whatever the Human has
}
public void setContents(){
for (HumanContentsContainer c : HumanContentsContainer.values()){
switch (c){
case CAR:{
this.car=c.getContainer();
}
}
//and so on
}
}
}
Edit
If you need to have a dynamic set of capabilities, I would suggest that you indeed keep the map of objects, and get rid of the ‘addCarMiles‘ method, as it implies that every human has a car.
I would implement public method on human ‘performCommand(CapabilityType, CapabilityCommand)‘ where the command will receive the capability and perform the operation on it. You may check out the Command Pattern tutorials.
Edit 2:
If all you want is to create a getter which will return dynamic type, you can use generics.
import java.io.Serializable;
import java.util.HashMap;
import java.util.NoSuchElementException;
public class Human implements Serializable {
private static final long serialVersionUID = 1748193556974180375L;
private HashMap<Class, Object> contents;
public void setContents(){
for (HumanContentsContainer c : HumanContentsContainer.values()){
contents.put(c.getContainer().getClass(), c.getContainer());
}
}
public HashMap<Class, Object> getContents(){
return contents;
}
public <T> T getContentsThatIsIntanceOf(Class<T> type){
Object object = contents.get(type);
if (object==null){
throw new NoSuchElementException("No such element: "+type.getName());
}
return type.cast(object);
}
public void usageExample(){
this.getContentsThatIsIntanceOf(ToyotaCar.class).addMiles(10);
}
}

Generic interface for enums in Java

I have a web-application on Hibernate / Spring and I have few enums that I want to use in applications
public enum MerchantStatus {
NEW("New"),
...
private final String status;
MerchantStatus(String status) {
this.status = status;
}
public static MerchantStatus fromString(String status) {..}
public String toString() {..}
}
And
public enum EmployerType {
COOL("Cool"),
...
private final String type;
EmployerType (String type) {
this.type = type;
}
public static EmployerType fromString(String type) {..}
public String toString() {..}
}
I want to create converter to convert my enum objects to string and and vice versa. It is something like this:
public class MerchantStatusConverter implements AttributeConverter<MerchantStatus, String> {
public String convertToDatabaseColumn(MerchantStatus value) {..}
public MerchantStatus convertToEntityAttribute(String value) {..}
}
The problem is that I don't want to create converter for each enum and ideally it should be generic class/interface and I will use polymorphism here. The problem is that fromString is static method and it seems that it is impossible to create static method that returns generic type.
Are there any solutions of this problem?
The problem is that I don't want to create converter for each enum and
ideally it should be generic class/interface and I will use
polymorphism here.
You have no choice as your AttributeConverter implementation could not be parameterized when you annotate your entity.
You should indeed specify it only with the AttributeConverter class :
#Enumerated(EnumType.STRING)
#Convert(converter = MerchantStatusConverter.class)
private MerchantStatus merchantStatus;
But you could define an abstract class that defines the logic and subclassing it in each enum class.
To achieve it, you should introduce an interface in front of each enum class that declares a fromString() and a toString() method.
The interface :
public interface MyEnum<T extends MyEnum<T>>{
T fromString(String type);
String toString(T enumValue);
}
The enum that implements the interface :
public enum MerchantStatus implements MyEnum<MerchantStatus> {
NEW("New"), ...
#Override
public MerchantStatus fromString(String type) {
...
}
#Override
public String toString(MerchantStatus enumValue) {
...
}
}
The abstract AttributeConverter class :
public abstract class AbstractAttributeConverter<E extends MyEnum<E>> implements AttributeConverter<E, String> {
protected MyEnum<E> myEnum;
#Override
public String convertToDatabaseColumn(E attribute) {
return myEnum.toString(attribute);
}
#Override
public E convertToEntityAttribute(String dbData) {
return myEnum.fromString(dbData);
}
}
And concrete AttributeConverter class that needs to declare a public constructor to assign the protected myEnum field to an enum value (whatever of it):
public class MerchantStatusAttributeConverter extends AbstractAttributeConverter<MerchantStatus> {
public MerchantStatusAttributeConverter(){
myEnum = MerchantStatus.NEW;
}
}
If you want a general Converter for all your enum classes, you can use reflection, as long as you stick to a naming convention.
Your convention seem to be that you use toString() for enum -> String conversion, and a static fromString(String) for String -> enum conversion.
A Converter for that would be something like this:
public class EnumConverter<T extends Enum<T>> implements AttributeConverter<T, String> {
private final Method fromStringMethod;
public EnumConverter(Class<T> enumClass) {
try {
this.fromStringMethod = enumClass.getDeclaredMethod("fromString", String.class);
} catch (NoSuchMethodException e) {
throw new NoSuchMethodError(e.getMessage());
}
if (! Modifier.isStatic(this.fromStringMethod.getModifiers()))
throw new NoSuchMethodError("fromString(String) is not static");
if (this.fromStringMethod.getReturnType() != enumClass)
throw new NoSuchMethodError("fromString(String) does not return " + enumClass.getName());
}
public String convertToDatabaseColumn(T value) {
return value.toString();
}
#SuppressWarnings("unchecked")
public T convertToEntityAttribute(String value) {
try {
return (T) this.fromStringMethod.invoke(null, value);
} catch (IllegalAccessException e) {
throw new IllegalAccessError(e.getMessage());
} catch (InvocationTargetException e) {
throw new RuntimeException("Error calling fromString(String): " + e, e);
}
}
}
You then construct it by naming the class, e.g.
new EnumConverter<>(MerchantStatus.class)
new EnumConverter<>(EmployerType.class)
You should be able to do the following:
public class Converter<T extends Enum<T>, U> implements AttributeConverter<T, U> {
public U convertToDatabaseColumn(T value) {
...
}
public T convertToEntityAttribute(U value) {
...
}
}

Categories