I have a piece of information that is stored in a database table as a string code value. I have defined an enum to make the code human-readable. An entity class defines the field with the enum.
When I display the data in a Vaadin grid, it displays the enumeration value, which is what is needed. However, I am also trying to display the same data in a form text field, and this behaves differently. I had to write a converter for the data binding to avoid a run-time error, but the result is the opposite of what I expect - it shows the code value instead of the enumeration.
Some code to illustrate:
The enumeration type:
public enum TaskType {
TASK_VIEW("00"), INTERACTIVE("01"), BATCH("02"), FOLDER("07"), URL("08"), USER_DEFINED("11");
private String codeValue;
private TaskType(String codeValue) {
this.codeValue = codeValue;
}
public String getCodeValue() {
return codeValue;
}
public static TaskType fromCodeValue(String value) {
switch (value) {
case "00":
return TASK_VIEW;
case "01":
return INTERACTIVE;
case "02":
return BATCH;
case "07":
return FOLDER;
case "08":
return URL;
case "11":
return USER_DEFINED;
default:
return null;
}
}
}
The entity class:
#Entity
public class TaskMaster extends AbstractEntity {
private TaskType type;
// other fields
public TaskType getType() {
return type;
}
public void setType(TaskType type) {
this.type = type;
}
// other methods
}
A converter between database field and enum type:
#Converter(autoApply = true)
public class TaskTypeConverter implements AttributeConverter<TaskType, String> {
#Override
public String convertToDatabaseColumn(TaskType type) {
if (type != null) {
return type.getCodeValue();
} else {
return null;
}
}
#Override
public TaskType convertToEntityAttribute(String dbData) {
if (dbData != null) {
return TaskType.fromCodeValue(dbData);
} else {
return null;
}
}
}
The grid view class:
public class TaskMasterListView extends VerticalLayout {
private Grid<TaskMaster> grid = new Grid<>(TaskMaster.class);
private TaskMasterService taskService;
public TaskMasterListView(TaskMasterService taskService) {
this.taskService = taskService;
...
}
#PostConstruct
public void init() {
List<TaskMaster> items = taskService.findAll();
grid.setItems(items);
}
private void configureGrid() {
grid.addClassName("tasks-grid");
grid.setColumns("internalTaskID", "taskID", "name", "type", "objectName", "version",
"formName");
grid.getColumns().forEach(col -> col.setAutoWidth(true));
}
...
}
The details view (where it displays incorrectly):
public class TaskDetailView extends FormLayout {
private static final Logger logger = LoggerFactory.getLogger(TaskDetailView.class);
private TextField type;
// other GUI objects
private Binder<TaskMaster> binder;
public TaskDetailView() {
configureView();
bindData();
}
public void loadTask(TaskTreeView.TaskSelectionEvent event) {
if (event.getSelected() != null) {
binder.setBean(event.getSelected());
}
}
private void bindData() {
binder = new Binder<>(TaskMaster.class);
binder.setBean(new TaskMaster());
binder.forField(type).withConverter(new TaskTypeConverter()).bind("type");
// other bindings
}
private static class TaskTypeConverter implements Converter<String, TaskType> {
#Override
public Result<TaskType> convertToModel(String value, ValueContext context) {
logger.info("convertToModel: value={}", value);
return Result.ok(TaskType.fromCodeValue(value));
}
#Override
public String convertToPresentation(TaskType value, ValueContext context) {
if (value != null) {
logger.info("convertToPresentation: value={}", value.toString());
return value.getCodeValue();
} else {
logger.info("convertToPresentation: null");
return "";
}
}
}
}
So, as an example, if an entity with type = 07 is displayed in the grid, it shows FOLDER, which is what I want. But, when I display the same object where the type is shown in a text field, it shows 07 instead of FOLDER.
Any idea what's going on here? It seems to be doing the opposite of what I need.
Your static class TaskTypeConverter is used to convert from TaskType.FOLDER by the binder. Now let's see what your convertToPresentation() does: it calls value.getCodeValue() so of course your TextField is filled with 07.
However, you want to return the enum name, so you need to call the inherent enum method value.name() and vice-versa call TaskType.valueOf(value) inside convertToModel(). Don't forget to catch IllegalArgumentException and NPE when calling valueOf()!
A good idea would be not to use .name() but a friendly name f.e. "Folder" which you can hold in your enum.
However, you should probably use a Select<TaskType> or ComboBox<TaskType> for the users to select from a predefined set of values i.e. from an enum, instead of a TextField.
Set the friendly name through setItemLabelGenerator() or a Renderer if you need to customize it more than just text.
Related
This would mean that the class was initialized, but the variables were not set.
A sample Class:
public class User {
String id = null;
String name = null;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
The actual class is huge that I prefer not to check if(xyz == null) for each of the variables.
Another non-reflective solution for Java 8, in the line of paxdiabo's answer but without using a series of if's, would be to stream all fields and check for nullness:
return Stream.of(id, name)
.allMatch(Objects::isNull);
This remains quite easy to maintain while avoiding the reflection hammer.
Try something like this:
public boolean checkNull() throws IllegalAccessException {
for (Field f : getClass().getDeclaredFields())
if (f.get(this) != null)
return false;
return true;
}
Although it would probably be better to check each variable if at all feasible.
This can be done fairly easily using a Lombok generated equals and a static EMPTY object:
import lombok.Data;
public class EmptyCheck {
public static void main(String[] args) {
User user1 = new User();
User user2 = new User();
user2.setName("name");
System.out.println(user1.isEmpty()); // prints true
System.out.println(user2.isEmpty()); // prints false
}
#Data
public static class User {
private static final User EMPTY = new User();
private String id;
private String name;
private int age;
public boolean isEmpty() {
return this.equals(EMPTY);
}
}
}
Prerequisites:
Default constructor should not be implemented with custom behavior as that is used to create the EMPTY object
All fields of the class should have an implemented equals (built-in Java types are usually not a problem, in case of custom types you can use Lombok)
Advantages:
No reflection involved
As new fields added to the class, this does not require any maintenance as due to Lombok they will be automatically checked in the equals implementation
Unlike some other answers this works not just for null checks but also for primitive types which have a non-null default value (e.g. if field is int it checks for 0, in case of boolean for false, etc.)
If you want this for unit testing I just use the hasNoNullFieldsOrProperties() method from assertj
assertThat(myObj).hasNoNullFieldsOrProperties();
How about streams?
public boolean checkFieldsIsNull(Object instance, List<String> fieldNames) {
return fieldNames.stream().allMatch(field -> {
try {
return Objects.isNull(instance.getClass().getDeclaredField(field).get(instance));
} catch (IllegalAccessException | NoSuchFieldException e) {
return true;//You can throw RuntimeException if need.
}
});
}
"Best" is such a subjective term :-)
I would just use the method of checking each individual variable. If your class already has a lot of these, the increase in size is not going to be that much if you do something like:
public Boolean anyUnset() {
if ( id == null) return true;
if (name == null) return true;
return false;
}
Provided you keep everything in the same order, code changes (and automated checking with a script if you're paranoid) will be relatively painless.
Alternatively (assuming they're all strings), you could basically put these values into a map of some sort (eg, HashMap) and just keep a list of the key names for that list. That way, you could iterate through the list of keys, checking that the values are set correctly.
I think this is a solution that solves your problem easily: (return true if any of the parameters is not null)
public boolean isUserEmpty(){
boolean isEmpty;
isEmpty = isEmpty = Stream.of(id,
name)
.anyMatch(userParameter -> userParameter != null);
return isEmpty;}
Another solution to the same task is:(you can change it to if(isEmpty==0) checks if all the parameters are null.
public boolean isUserEmpty(){
long isEmpty;
isEmpty = Stream.of(id,
name)
.filter(userParameter -> userParameter != null).count();
return isEmpty > 0
}
The best way in my opinion is Reflection as others have recommended. Here's a sample that evaluates each local field for null. If it finds one that is not null, method will return false.
public class User {
String id = null;
String name = null;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public boolean isNull() {
Field fields[] = this.getClass().getDeclaredFields();
for (Field f : fields) {
try {
Object value = f.get(this);
if (value != null) {
return false;
}
}
catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return true;
}
public static void main(String args[]) {
System.out.println(new User().isNull());
}
}
Field[] field = model.getClass().getDeclaredFields();
for(int j=0 ; j<field.length ; j++){
String name = field[j].getName();
name = name.substring(0,1).toUpperCase()+name.substring(1);
String type = field[j].getGenericType().toString();
if(type.equals("class java.lang.String")){
Method m = model.getClass().getMethod("get"+name);
String value = (String) m.invoke(model);
if(value == null){
... something to do...
}
}
Best for me is
Stream.of(getClass().getDeclaredMethods()).allMatch(Objects::isNull);
It can be used in a custom annotation + annotation processor to automagically define a boolean isNull() method on the annotated classes.
Based on Irkwz's answer, but a different approach:
public class SomeClass{
private String field1;
private String field2;
private ComplexField field3;
private String field4;
private Integer field15;
public boolean isNullAllFields() {
return Stream.of(this.getClass().getDeclaredFields()).anyMatch(element -> (element != null));
}
}
And the end of the day u invoke isNullAllFields method to figure out wheter the object fields are empty.
If you want to do the opposite i.e check if some/all members of class are non-non, the check this answer.
In order to make sure that certain members of the class are always non-null, we can use lombok #NonNull annotation on the individual fields of the class.
import lombok.Data;
import lombok.NonNull;
#Data
public class DataClass {
#NonNull
private String data1;
private int data2;
#NonNull
private String data3;
#NonNull
private String data4;
#NonNull
private String data5;
private String data6;
DataClass(String data1,...) {
// constructor
}
}
Easiest way is to convert the class to a map and get its keys and with stream check if any or all key's values are null or not, you can take input from user as well whether they want to check for specific set of keys only!
Below is the code to check whether any of the key's value has null, you can change stream config to all match or any match as per your requirement
Just replace isNullOrEmpty method i have used with proper null or empty check condition for that particular collection
public boolean checkIfAnyFieldIsNull(Object instance, Set<String> fields){
try {
Map<String, Object> instanceMap = new Gson().fromJson(new GsonBuilder().serializeNulls().create().toJson(instance), Map.class);
if(!isNullorEmpty(instanceMap)) {
fields = isNullorEmpty(fields) ? instanceMap.keySet() : fields;
return fields.stream().anyMatch(curField -> isNull(instanceMap.get(curField)));
}else{
return false;
}
}catch (Exception e){
return false;
}
}
}
Try this method once, its works for me!!
private fun checkIfAnyDataIsNull(model: YourModelCass): Boolean {
return Stream.of<Any>(
model.date,
model.merchantName,
model.payment,
).allMatch(Objects::isNull)
}
You can use the simple solution:
if(user.equals(new User()){
//your processing goes here
}
how can i convert this field in to Java Class field where myText field can be conditionally one of this format:
{
"myText" : "Values
}
{
"myText" : ["text": "Values", "text2" : "Values"]
}
public class MyClass {
private String myText;
//or
private MyText myText;
}
public class MyText {
private String text1;
private String text2;
}
Welll.. you shouldn't do that in the first place.
But sometimes there is a case when some badly written rest api will return something like that. I have one solution which we are using only for parsing and sending through data.
So it works for us, but may not work for you
public class ListOrNotList {
protected ListOrNotList() {
}
protected String get(Object item) {
if (item instanceof String) {
return (String)item;
} else if (item instanceof List) {
for (Object it : (List)item) {
if (it instanceof LinkedHashMap) {
LinkedHashMap hashMap = (LinkedHashMap) it;
if (hashMap.containsKey("value")) {
Object value = hashMap.get("value");
if (value == null) {
return null;
}
return value.toString();
}
}
}
}
return null;
}
}
Then you make your class MyClass which extends from ListOrNotList
public class MyClass extends ListOrNotList {
private Object myText;
public String getMyText() {
return get(myText); //This is method from ListOrNotList class
}
}
This is not 100% working solution for OP, just an idea how it can be handled
In this example get function returns string or first element from List
you could also implement casting to T type in that method if you have a specific type and want to use any operations on it.
If you are creating api yourself then don't do things like returning different datatypes with the same name, it's bad practice and will harm development when anyone will try to integrate it in an app (including you after few months)
I need to get the enum name based on value. I am given with enum class and value and need to pick the corresponding name during run time .
I have a class called Information as below.
class Information {
private String value;
private String type;
private String cValue;
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getcValue() {
return cValue;
}
public void setcValue(String cValue) {
this.cValue = cValue;
}
public static void main(String args[]) {
Information inf = new Information();
inf.setType("com.abc.SignalsEnum");
inf.setValue("1");
}
}
class SignalEnum {
RED("1"), GREEN("2"), ORANGE("3");
private String sign;
SignalEnum(String pattern) {
this.sign = pattern;
}
}
class MobileEnum {
SAMSUNG("1"), NOKIA("2"), APPLE("3");
private String mobile;
MobileEnum(String mobile) {
this.mobile = mobile;
}
}
In run time i will come to know the enum name using the attribute type from the Information class and also i am getting the value. I need to figure out the corresponding enum to set the value for cValue attribute of Information class.
Just for example i have provided two enums like SignalEnum and MobileEnum but in my actual case i will get one among 100 enum types. Hence i dont want to check type cast. I am looking for some solution using reflection to se the cValue.
Here is a simple resolver for any enum class.
Since reflection operations are expensive, it's better to prepare all required data once and then just query for it.
class EnumResolver {
private Map<String, Enum> map = new ConcurrentHashMap<>();
public EnumResolver(String className) {
try {
Class enumClass = Class.forName(className);
// look for backing property field, e.g. "sign" in SignalEnum
Field accessor = Arrays.stream(enumClass.getDeclaredFields())
.filter(f -> f.getType().equals(String.class))
.findFirst()
.orElseThrow(() -> new NoSuchFieldException("Not found field to access enum backing value"));
accessor.setAccessible(true);
// populate map with pairs like ["1" => SignalEnum.RED, "2" => SignalEnum.GREEN, etc]
for (Enum e : getEnumValues(enumClass)) {
map.put((String) accessor.get(e), e);
}
accessor.setAccessible(false);
} catch (ReflectiveOperationException e) {
throw new RuntimeException(e);
}
}
public Enum resolve(String backingValue) {
return map.get(backingValue);
}
private <E extends Enum> E[] getEnumValues(Class<E> enumClass) throws ReflectiveOperationException {
Field f = enumClass.getDeclaredField("$VALUES");
f.setAccessible(true);
Object o = f.get(null);
f.setAccessible(false);
return (E[]) o;
}
}
And here is simple JUnit test
public class EnumResolverTest {
#Test
public void testSignalEnum() {
EnumResolver signalResolver = new EnumResolver("com.abc.SignalEnum");
assertEquals(SignalEnum.RED, signalResolver.resolve("1"));
assertEquals(SignalEnum.GREEN, signalResolver.resolve("2"));
assertEquals(SignalEnum.ORANGE, signalResolver.resolve("3"));
}
#Test
public void testMobileEnum() {
EnumResolver mobileResolver = new EnumResolver("com.abc.MobileEnum");
assertEquals(MobileEnum.SAMSUNG, mobileResolver.resolve("1"));
assertEquals(MobileEnum.NOKIA, mobileResolver.resolve("2"));
assertEquals(MobileEnum.APPLE, mobileResolver.resolve("3"));
}
}
And again for performance sake you can also instantiate these various resolvers once and put them into a separate Map
Map<String, EnumResolver> resolverMap = new ConcurrentHashMap<>();
resolverMap.put("com.abc.MobileEnum", new EnumResolver("com.abc.MobileEnum"));
resolverMap.put("com.abc.SignalEnum", new EnumResolver("com.abc.SignalEnum"));
// etc
Information inf = new Information();
inf.setType("com.abc.SignalsEnum");
inf.setValue("1");
SignalEnum red = (SignalEnum) resolverMap.get(inf.getType()).resolve(inf.getValue());
I have a String property that relates to calling a particular method.
I have this DTO, with an icon property
public class MyDto
{
String icon; // "first", "second", "third" etc
public String getIcon()
{
return icon;
}
}
In my interface I have these methods: (GWT ClientBundle)
public interface MyClientBundle extends ClientBundle
{
#Source("icon_first.jpg")
ImageResource icon_first();
#Source("logo_second.jpg")
ImageResource icon_second();
#Source("icon_third.jpg")
ImageResource icon_third();
}
I'm currently using an inefficient lookup with selection statements, but want to select the right method by building a string instead:
public ImageResource getValue(MyDto object)
{
return getIconFromCode(object.getIcon());
}
private ImageResource getIconFromCode(String code)
{
if(code.equalsIgnoreCase("first"))
{
return resources.icon_first();
}
else if(code.equalsIgnoreCase("second"))
{
return resources.icon_second();
}
else if(code.equalsIgnoreCase("third"))
{
return resources.icon_third();
}
else
{
return resources.icon_default();
}
}
I want to build a string to select the right method instead, something like "icon_" + object.getIcon()+ "()"
Having done some research I understand I need to use reflection? How would this be accomplished?
The interface MyClientBundle should extends ClientBundleWithLookup instead of ClientBundle.
The ClientBundleWithLookup has a getResource(String name) method that lets you retrieve the resource from the resource name (method name).
Cache the getter methods by the icon name from the annotation and use that cache to call the getters.
The code below only gets the annotations from interfaces one level up. If you need to go higher for some reason, just recursively call the cacheGettersFor() method.
There is no check here to make sure the icon getter methods have the right signature (take no arguments, return ImageResource), you'll want to add that if you use any of this code.
public class IconGetterCache {
class IconGetterCacheForBundleType {
private Map<String, Method> _iconGetters = new HashMap<>();
private Class<?> _runtimeClass;
private void cacheGettersFor(Class<?> forClazz) {
for (Method method : forClazz.getMethods()) {
Source iconSourceAnnotation = method.getAnnotation(Source.class);
if (iconSourceAnnotation != null) {
_iconGetters.put(iconSourceAnnotation.value(), method);
}
}
}
IconGetterCacheForBundleType(final Class<?> runtimeClass) {
_runtimeClass = runtimeClass;
for (Class<?> iface : _runtimeClass.getInterfaces()) {
cacheGettersFor(iface);
}
cacheGettersFor(_runtimeClass);
}
public ImageResource getIconFromBundle(ClientBundle bundle, String iconName) {
if (!_runtimeClass.isAssignableFrom(bundle.getClass())) {
throw new IllegalArgumentException("Mismatched bundle type");
}
Method getter = _iconGetters.get(iconName);
if (getter == null) { return null; }
try {
return (ImageResource) getter.invoke(bundle);
}
catch (Throwable t) {
throw new RuntimeException("Could not get icon", t);
}
}
}
private Map<Class<?>, IconGetterCacheForBundleType> _getterCaches = new HashMap<>();
//main entry point, use this to get your icons
public ImageResource getIconFromBundle(ClientBundle bundle, String iconName) {
final Class<? extends ClientBundle> getterClass = bundle.getClass();
IconGetterCacheForBundleType getterCache = _getterCaches.get(getterClass);
if (getterCache == null) {
_getterCaches.put(getterClass, getterCache = new IconGetterCacheForBundleType(getterClass));
}
return getterCache.getIconFromBundle(bundle, iconName);
}
}
//Here's how I tested
IconGetterCache gc = new IconGetterCache();
MyClientBundle concreteClientBundle = new MyClientBundle() {
#Override
public ImageResource icon_first() {
//return correct icon
}
#Override
public ImageResource icon_second() {
//return correct icon
}
#Override
public ImageResource icon_third() {
//return correct icon
}
};
gc.getIconFromBundle(concreteClientBundle, "icon_first.jpg");
I'm learning about Java enums and I was wondering what is the best approach to check multiple enums for a matching value in order to call a specific method. I have defined two separate enums below that are used by getValue method's colName parameter to determine what method to execute. So the enum drives the method call. There has to be a more efficient way to do this than what I have below. Any suggestions?
I want to avoid having to do the below (pseudo code):
if(colName.equalsIgnoreCase("ATTRIBUTEONE") ||
colName.equalsIgnoreCase("ATTRIBUTETWO") ||
colName.equalsIgnoreCase("ATTRIBUTETWO")){
callAsStringMethod();
} else if(colName.equalsIgnoreCase("ATTRIBUTEFOUR")){
callAsIntegerMethod();
}
My Attempt using enum:
public class RowHelper implements IRowHelper
public static enum StringAttributes {
ATTRIBUTEONE,
ATTRIBUTETWO,
ATTRIBUTETHREE;
}
public static enum IntegerAttributes {
ATTRIBUTEFOUR,
ATTRIBUTEFIVE,
ATTRIBUTESIX,
ATTRIBUTESEVEN;
}
#Override
public String getValue(String colName) throws Exception{
boolean colFound=false;
Object retValue = null;
for (EConstants.StringAttributes attribute : EConstants.StringAttributes.values()) {
if(colName.toUpperCase().equals(attribute)){
retValue = callAsStringMethod();
colFound=true;
}
}
for (EConstants.IntegerAttributes attribute : EConstants.IntegerAttributes.values()) {
if(colName.toUpperCase().equals(attribute)){
retValue = callAsIntegerMethod();
colFound=true;
}
}
if(!colFound)
throw new Exception("column not found");
if(retValue instanceof String )
return (String) retValue;
else
return retValue.toString();
}
}
Try this:
public String getValue(String colName) throws Exception {
final String name = colName != null ? colName.trim().toUpperCase() : "";
try {
EConstants.StringAttributes.valueOf(name);
return callAsStringMethod().toString();
} catch (Exception e1) {
try {
EConstants.IntegerAttributes.valueOf(name);
return callAsIntegerMethod().toString();
} catch (Exception e2) {
throw new Exception("column not found");
}
}
}
The method's now returning the appropriate value, according to the latest edit of the question.
EDIT :
According to Kirk Woll and Louis Wasserman's benchmark, looping through values is significantly faster than doing a try/catch. So here's a simplified version of the original code, expect it to be a bit faster:
public String getValue(String colName) throws Exception {
final String name = colName != null ? colName.trim().toUpperCase() : "";
for (EConstants.StringAttributes attribute : EConstants.StringAttributes.values())
if (name.equals(attribute))
return callAsStringMethod().toString();
for (EConstants.IntegerAttributes attribute : EConstants.IntegerAttributes.values())
if (name.equals(attribute))
return callAsIntegerMethod().toString();
throw new Exception("column not found");
}
Well, this is a weird design ._. Anyway, you can use enum, but I would something like:
public interface RowAttribute {
String getValue(IRowHelper rowHelper);
}
public class StringRowAttribute implements RowAttribute {
#Override
public String getValue(IRowHelper rowHelper) {
return rowHelper.callAsStringMethod();
}
}
public class IntegerRowAttribute implements RowAttribute {
#Override
public String getValue(IRowHelper rowHelper) {
return rowHelper.callAsIntegerMethod().toString();
}
}
public class RowHelper implements IRowHelper {
private static final RowAttribute INTEGER_ATTRIBUTE = new IntegerRowAttribute();
private static final RowAttribute STRING_ATTRIBUTE = new StringRowAttribute();
private static enum Attribute {
ATTRIBUTEONE(INTEGER_ATTRIBUTE),
ATTRIBUTETWO(INTEGER_ATTRIBUTE),
ATTRIBUTETHREE(INTEGER_ATTRIBUTE);
ATTRIBUTEFOUR(STRING_ATTRIBUTE),
ATTRIBUTEFIVE(STRING_ATTRIBUTE),
ATTRIBUTESIX(STRING_ATTRIBUTE),
ATTRIBUTESEVEN(STRING_ATTRIBUTE);
private final RowAttribute attribute;
private Attribute(RowAttribute attribute) {
this.attribute = attribute;
}
public RowAttribute getAttributeResolver() {
return this.attribute;
}
}
#Override
public String getValue(String colName) throws Exception {
final String name = colName != null ? colName.trim() : "";
for (Attribute attribute : Attribute.values()) {
if (attribute.name().equalsIgnoreCase(name)) {
return attribute.getAttributeResolver().getValue(this);
}
}
throw new Exception(String.format("Attribute for column %s not found", colName));
}
}
Then you don't need to create more than one enum and use its power to iterate through the possible values. You would only need to make the methods callAsStringMethod/callAsIntegerMethod public. Another way is to insert the implementations inside RowHelper. Something like this:
public class RowHelper implements IRowHelper {
public interface RowAttribute {
String getValue();
}
private static final RowAttribute INTEGER_ATTRIBUTE = new RowAttribute() {
#Override
public String getValue() {
return callAsIntegerMethod().toString();
}
};
private static final RowAttribute STRING_ATTRIBUTE = new RowAttribute() {
#Override
public String getValue() {
return callAsStringMethod();
}
};
...
#Override
public String getValue(String colName) throws Exception {
...
if (attribute.name().equalsIgnoreCase(name)) {
return attribute.getAttributeResolver().getValue();
}
...
}
}
Anyway, I don't understand in your method how you get the attribute value really without passing as parameter the colName to it.
The most efficient way to do this with multiple enums is, frankly, to make them the same enum. There isn't really a better way.
That said, instead of the loop you have, you can use Enum.valueOf(EnumClass.class, name) to find the enum value of that type with the specified name, rather than looping like you're doing.