I have some UI client filters (combobox and checkbox group) that I need to use on server side: I thought to use an enum to identify filter types and others enums to identify each filter's options.
// All UI filters
public enum FilterType {
AGGREGATION("aggregation"),
AREA("area"),
PRODUCTION("production"),
DATA_TYPE("datatype"),
PRODUCER("producer"),
NETWORK("network"),
SOURCE("source");
private String value;
private FilterType(String value) {
this.value = value;
}
public String getValue() {
return value;
}
}
// FilterType.AGGREGATION filter options
public enum AggregationOptionType {
STANDARD("standard"),
DTR("dtr"),
CO("co");
private String value;
private AggregationOptionType(String value) {
this.value = value;
}
public String getValue() {
return value;
}
}
I would like to craete a hard link between FilterType.AGGREGATION and AggregationOptionType forcing the access to an option via FilterType.AGGREGATION.DTR.
How can I "nest" an enum inside a value of another enum?
Are there other patterns (maybe smarter than mine) to achieve the same result?
EDIT
A clarification: I do NOT need to assign to each value of the outer enum a value of a common inner enum. I need to assign a whole different inner enum to each value of the outer enum.
You can put one enum into another, like:
enum OuterEnum {
A, B;
enum InnerEnum {
C, D;
}
}
To use like:
class Enumuser {
OuterEnum.InnerEnum ie = OuterEnum.InnerEnum.C;
}
But of course, that is not exactly what you are looking for.
You need to go one step further:
enum OuterEnum {
A(InnerEnum.C), B(InnerEnum.D);
private final InnerEnum inner;
private OuterEnum(InnerEnum inner) { this.inner = inner; }
public InnerEnum getInner() { return inner; }
enum InnerEnum {
C, D;
}
}
class Enumuser {
OuterEnum.InnerEnum inner = OuterEnum.A.getInner();
}
But a final word of warning: don't get too hang up on using enums for such purposes. You see, as soon as you start writing switch statements all over the place that switch over such enums, in order to do this or that ... you are probably doing something wrong. Consider not "falling into that enum trap" please.
Instead you should be looking into using polymorphism, like shown here!
You can add it to the Enum, as a variable.
But only if you can have all the sub Enums under the same enum type ie
public enum FilterType {
AGGREGATION("aggregation",Subfilter.DTR);
}
You can do something like as follows:
//All UI filters
public interface FilterType {
// FilterType.AGGREGATION
public interface AGGREGATION {
// FilterType.AGGREGATION filter options
enum AggregationOptionType {
STANDARD("standard"),
DTR("dtr"),
CO("co");
private String value;
private AggregationOptionType(String value) {
this.value = value;
}
public String getValue() {
return value;
}
}
}
}
e.g. for AGGREGATION
Just use it in the same way like a String value and if you want to have a single file, so hold your enums in a interface class:
public interface Enums {
public enum FilterType {
AGGREGATION("aggregation", AggregationOptionType.DTR),
AREA("area"),
PRODUCTION("production"),
DATA_TYPE("datatype"),
PRODUCER("producer"),
NETWORK("network", AggregationOptionType.CO),
SOURCE("source");
public final String value;
public final AggregationOptionType type;
private FilterType(String value, AggregationOptionType typy) {
this.value = value;
this.type = typy;
}
private FilterType(String value) {
this.value = value;
this.type = AggregationOptionType.STANDARD;
}
}
public enum AggregationOptionType {
STANDARD("standard"),
DTR("dtr"),
CO("co");
public final String value;
private AggregationOptionType(String value) {
this.value = value;
}
}
}
Related
Good day SO people. I have a problem regarding returning the inner enum values of my enum. I do not know which return type to use. I have tried googling and bumped into some solutions the uses generics however, I still have no luck. I do not know if my question has a solution or probably I did a bad design. So here goes, below
is my enum.
public enum KEYS
{
A("value"),
B("value"),
C("value");
public enum KEYS_GROUP_A
{
ITEM_A ("value"),
ITEM_B ("value"),
ITEM_C ("value");
private String value;
private KEYS_GROUP_A( String _value )
{
value = _value;
}
public String getVal()
{
return value;
}
}
public enum KEYS_GROUP_B
{
ITEM_A ("value"),
ITEM_B ("value"),
ITEM_C ("value");
private String value;
private KEYS_GROUP_B( String _value )
{
value = _value;
}
public String getVal()
{
return value;
}
}
public enum KEYS_GROUP_C
{
ITEM_A ("value"),
ITEM_B ("value"),
ITEM_C ("value");
private String value;
private KEYS_GROUP_C( String _value )
{
value = _value;
}
public String getVal()
{
return value;
}
}
private String value;
private PROPERTY_KEYS(String _value)
{
value = _value;
}
public String getVal()
{
return value;
}
public <?> getEnumValues(int x)
{
if ( 0 == x )
{
return KEYS.KEYS_GROUP_A.values();
}
else if ( 1 == x )
{
return KEYS.KEYS_GROUP_B.values();
}
else
{
return KEYS.KEYS_GROUP_C.values();
}
}
}
What I am trying to do is the getEnumValues() method. I have tried the return type <T extends Enum<T>> T but still an error occurs. Please tell if my design is bad or should not really be done. Please state some references. I'm willing to read and learn. Please shed some light! Thanks in advance!
The most specific type you can return is
public Enum<?>[] getEnumValues(int x)
You can return a more "useful" type if you define an interface like this:
interface HasVal { String getVal(); }
then make your enums all implement that interface, e.g.:
public enum KEYS_GROUP_A implements HasVal {
// ...
#Override public String getVal() { return value; }
}
Then you can return
public HasVal[] getEnumValues(int x)
and be able to invoke the getVal method on the instances:
for (HasVal val : getEnumValues(x)) {
System.out.println(val.getVal());
}
You can't use:
public <T extends Enum<T>> T[] getEnumValues(int x)
because this isn't satisfiable for a general T. For instance, I could define:
enum Blah {}
and then try to invoke:
Blah[] blah = getEnumValues(1);
That wouldn't be type safe, because at least one (well, all, actually) of the code paths return a value which is not covariant with Blah[].
Is it possible to create a generic method or class to retrieve an enum value from a given unique property (field with getter method)?
So you would have:
public enum EnumToMap {
E1("key1"),
E2("key2"),
;
private final String key;
private EnumToMap(String key) {
this.key = key;
}
public String getKey() {
return key;
}
}
so required is the same functionality as
public static EnumToMap getByKey(String key)
...
would provide. Preferably without reflection and as generic as possible (but in this case it may not be possible to create a generic solution without reflection).
Clarification: So this method should work for multiple enumerations. The idea is not to have to implement the lookup over and over again.
Actually possible just with generics and interface.
Create and implement interface
interface WithKeyEnum {
String getKey();
}
enum EnumToMap implements WithKeyEnum {
...
#Override
public String getKey() {
return key;
}
}
Implementation
public static <T extends Enum<T> & WithKeyEnum> T getByKey(Class<T> enumTypeClass, String key) {
for (T type : enumTypeClass.getEnumConstants()) {
if (type.getKey().equals(key)) {
return type;
}
}
throw new IllegalArgumentException();
}
Usage
EnumToMap instanceOfE1 = getByKey(EnumToMap.class, "key1");
If you want to drop generification and get O(1) complexity use HashMap to get it
public enum EnumToMap{
E1("key1"),
E2("key2");
private final String key;
private static final Map<String, EnumToMap> keys = new HashMap<String, EnumToMap>();
static {
for (EnumToMap value : values()) {
keys.put(value.getKey(), value);
}
}
private EnumToMap(String key) {
this.key = key;
}
public String getKey() {
return key;
}
public static EnumToMap getByKey(String key) {
return keys.get(key);
}
}
This would be hard to just generify as there must be an object to store the map. Enum itself seems to be good candidate for that.
I have to define the class below in ESPER so I'm able to reference the sub-types and internal arrays. I have to do it pragmatically. I don't care how:
UPDATE: The complete class:
public class IoTEntityEvent implements java.io.Serializable {
private IoTProperty[] Properties;
private String About;
IoTEntityEvent (){
this.About = null;
this.Properties = null;
}
public String getAbout() {
return About;
}
public void setAbout( String value){
this.About = value;
}
public void setProperties(int index, IoTProperty value) {
Properties[index] = value;
}
public IoTProperty getProperties(int index) {
return Properties[index];
}
public void setProperties( IoTProperty[] value) {
Properties = value;
}
public IoTProperty[] getProperties() {
return Properties;
}
}
This is the sub-class:
public class IoTProperty implements java.io.Serializable {
private Map<String,String>[] IoTStateObservation =null;
private String About = null;
IoTProperty (){
this.About = null;
this.IoTStateObservation = null;
}
public String getAbout() {
return About;
}
public void setAbout(String value) {
About = value;
}
public Map<String,String>[] getIoTStateObservation() {
return IoTStateObservation;
}
public void setIoTStateObservation( Map<String,String>[] value) {
IoTStateObservation = value;
}
public Map<String,String> getIoTStateObservation(int index) {
return IoTStateObservation[index];
}
public void setIoTStateObservation(int index, Map<String,String> value) {
IoTStateObservation[0] = value;
}
}
I tried like this :
eventNames[0] = "About";
eventType[0] = String.class;
eventNames[1] = "Properties";
eventType[1] = IoTProperty[].class;
epService.getEPAdministrator().getConfiguration().addEventType("type", eventNames, eventType);
This works but I can't access the sub-types. I also tried to define the sub type in similar manner. Can someone can explain how I suppose to do it?
What do you mean with "This works but I can't access the sub-types."
Tried like "select Properties[0].whatever" from type?
According to the Esper documentation:
Plain-old Java object events are object instances that expose event properties through JavaBeans-style getter methods. Events classes or interfaces do not have to be fully compliant to the JavaBean specification; however for the Esper engine to obtain event properties, the required JavaBean getter methods must be present or an accessor-style and accessor-methods may be defined via configuration.
In short, you need to create the JavaBean getters and setters in order to access your private members.
Thank you for the help. I found out how and is as following:
epService.getEPAdministrator().getConfiguration().addEventType("type",IoTEntityEvent.class);
Then the event should be send like this without any casting:
IoTValue[] va= {new IoTValue("0.62","2014-06-09T18:08:40.968Z","2014-06-09T18:08:40.968Z")};
IoTProperty[] pr = {new IoTProperty(va,"property")};
IoTEntityEvent event = new IoTEntityEvent(pr,"Entity");
epService.getEPRuntime().sendEvent(event);
I am trying to implement a solution (in Java 1.6) where i need to store some values (for a set of properties) and thinking in three options considering the following three (Any other idea is of course wellcome!)
Option 1
Create a class (call it Property) that can store different type of objects (String, int, boolean...) and and work with the set of properties as a List<Property>
Something like:
private String type; //Store the type of Object
private String name; //Store the name of the property
private String valueStr; //Store the String value
private int valueInt; //Store the int value
private boolean valueBool; //Store the boolean value
I dont really like the idea of having many properties and using only one of them. (only one of the values will be set per property)
Option 2
Use HashMap<String, Object> and parse the type on each case.
Have the good thing that you can get the Property by name
Option 3
Use HashMap<String, Property> Where the String is the name of the property and you can get the value with the name and no need to parse.
Questions are:
Which of one you think is the best one?
or if none of them are good i would like to hear other ideas
Also is there any performance difference between the List and the HashMap?
Thanks in advance for the help.
I think better is to have a custom Value class like this:
public class MyValue {
enum Type {
INT, STRING, BOOL;
}
private Type type; //Store the type of Object in Type Enum
private Object value; //Store the value in Object
public void setValue(int val) {
type = Type.INT;
value = new Integer(val);
}
public void setValue(String val) {
type = Type.STRING;
value = val;
}
public void setValue(boolean val) {
type = Type.BOOL;
value = new Boolean(val);
}
public String stringVal() {
// check type to be STRING first
return (String) value;
}
public int intVal() {
// check type to be INT first
return ((Integer) value.intValue());
}
public boolean booleanVal() {
// check type to be BOOL first
return ((Boolean) value.booleanValue());
}
}
You will need to convert from Object to specific type based on enum Type in your getters.
Another option would be something like this, using inheritance rather than keeping a large number of unused fields around.
public interface Property {
String getType();
String getName();
Object getValue();
}
public abstract class AbstractProperty implements Property {
private final String name;
protected AbstractProperty(String name) {
this.name = name;
}
}
public class StringProperty extends AbstractProperty {
private final String value;
public StringProperty(String name, String value) {
super(name);
this.value = value;
}
#Override
public String getType() {
return String.class.getName();
}
#Override
public String getValue() {
return value;
}
}
public class IntegerProperty extends AbstractProperty {
private final Integer value;
public IntegerProperty(String name, Integer value) {
super(name);
this.value = value;
}
#Override
public String getType() {
return Integer.TYPE.getName();
}
#Override
public Integer getValue() {
return value;
}
}
I think option 2 would be the best for you. Considering that you are storing properties I am expecting that you would be querying this list quite often which again points in the direction of a HashMap as that would make your lookup very efficient.
I suggest using an enum instead. Enums are good for holding lists of values, and are effective at retrieval.
public enum Property {
TYPE,
NAME,
VALUEINT; //...
private String sProp = "";
private int iProp = 0;
private boolean bProp = false;
public String getStringProp() {return sProp;}
public int getIntProp() {return iProp;}
public boolean getBoolProp() {return bProp;}
public void setStringProp(String str) {this.sProp = str;}
public void setIntProp(int i) {this.iProp = i;}
public void setBoolProp(boolean b) {this.bProp = b;}
}
This can then be accessed with Property.TYPE, Property.VALUEINT, etc. You can set properties with Property.TYPE.setStringProp(), and get them with Property.TYPE.getStringProp().
You can read more about enums from Oracle's site.
I am unsure if there's one 'best' way. It really depends on how the data would be used after storing in a data structure.
In cases when I just need to accumulate properties and do something on each of them, I'd use a list, or even an array, sometimes.
If you might have to get a particular property, say by name, then a HashMap could help.
Again if you want to use the native object type or an instance of Property depends on what kind of data you have.
Which performs better depends on the number of objects you have, how you'd access them for use, how often you'd insert and several other factors.
I have the following enumeration in Java on Android and I would like to be able to deserialize an integer in an incoming JSON string/object into this Enum type. I have been getting hits on Jackson and GSON but nothing on the JSON.org package, which I am using.
Is there an easy way to do this or do I need to alter the JSON decoder? Thanks.
public enum ValueEnum {
ONE(1),
TWO(2),
THREE(3);
private int value;
private ValueEnum(int value) {
this.value = value;
}
public int getValue() {
return value;
}
}
ValueEnum.values() will return you array of ValueEnum[] then you can iterate over array and check for Value
public static ValueEnum valueOf(int value) {
ValueEnum[] valueEnums = ValueEnum.values();
for (ValueEnum valueEnum : valueEnums) {
if (valueEnum.getValue() == value)
{
return valueEnum;
}
}
return DEFAULT;
}