enums with custom methods for value of

958 views
Skip to first unread message

jmcg...@gmail.com

unread,
Apr 16, 2014, 11:59:34 AM4/16/14
to snakeya...@googlegroups.com
Hi,

For various reasons I have data files that represent values with dashes in them that I'd like to map into a java enumerated type.

In java, I have an enum like
public enum MyEnum {
value_1("value-1"),
value_2("value-2"),
//...
;

private string dataValue;
private static Map<String,MyEnum> map = new HashMap<String,MyEnum>();
static {
for (MyEnum key : values() {
map.put(key.dataValue, key);
}
}
private MyEnum(final String dataValue)
{
this.dataValue = dataValue;
}

public statuc final MyEnum getYamlValue(string yamlString)
{
final MyEnum = map.get(yamlString);
if (retval == null)
throw new IllegalArgumentExceptin("Invalid value: " + yamlString);
return retval;
}
@Override
public final String toString()
{
return dataValue;
}
}
Along with a class that uses the above enum:
public class DataClass {
Public String description;
Public MyEnum value;
}

And a YAML file that looks like
description: some description
value: value-1

I've experimented with Constructor/TypeDescription/Tag:
public class MyEnumYaml extends AbstractConstruct {
@Override
public Object construct(Node node) {
ScalarNode scalar = (ScalarNode) node;
String nodeValue = scalar.getValue();
MyEnum retval = MyEnum.getYamlValue(nodeValue);
return retval;
}
along with loading code like:
//...
Constructor c = new Constructor(DataClass.class);
TypeDescription t = new TypeDescription(MyEnumYaml.class, new Tag(MyEnum.class));
c.addTypeDescription(t);
Yaml yaml new Yaml(c);
DataClass dc = (DataClass) yaml.load(inputStream);

Which does not work as enum.valueOf is still being invoked.

Is there a different way I can tell SnakeYaml to use a different constructor for enums instead of enum.valueOf()?

Thanks,
John




Joachim Durchholz

unread,
Apr 16, 2014, 1:55:29 PM4/16/14
to snakeya...@googlegroups.com
Am 16.04.2014 17:59, schrieb jmcg...@gmail.com:
> Is there a different way I can tell SnakeYaml to use a different
> constructor for enums instead of enum.valueOf()?

Java simply does not allow to use a constructor on an enum (with a reason).
Java enums are for the use case that the Java side defines a fixed set
of values. So deserialization cannot *construct* an enum value, it can
only *select* one of the provided values.

If it's the database that defines what values exist, an enum simply
doesn't fit, you'll need a normal value type.

If it's indeed an enum, you'll have to write your own implementation for
valueOf.
E.g. I tend to write something like this:
enum Foo {
value_1("value-1"),
value_2("value_2");
private Foo(String databaseString) {
this.databaseString = databaseString;
dbToEnum.put(databaseString, this);
}
private static Map<String, Foo> dbToEnum
= new HashMap<String, Foo>();
public static Foo fromDbString(String dbString) {
return dbToEnum.get(dbString);
}
}
// Warning: unpolished&untested code

A HashMap might be overkill. AFAIK the valueOf function simply iterates
over all values of the enum and returns the first match.

jmcg...@gmail.com

unread,
Apr 17, 2014, 9:50:30 AM4/17/14
to snakeya...@googlegroups.com


On Wednesday, April 16, 2014 1:55:29 PM UTC-4, toolforger wrote:
> Java simply does not allow to use a constructor on an enum (with a reason).

Understood.  That's why my example includes the getYamlValue() which pulls the enum from the HashMap.

I suppose I should have phrased my question like "is there a way I can use SnakeYaml Construct/Constructor/TypeDescription/Tag to invoke my getYamlValue() instead of enum.valueOf()?".

Thanks,
John

Joachim Durchholz

unread,
Apr 17, 2014, 11:59:57 AM4/17/14
to snakeya...@googlegroups.com
Am 17.04.2014 15:50, schrieb jmcg...@gmail.com:
>
>
> On Wednesday, April 16, 2014 1:55:29 PM UTC-4, toolforger wrote:
>>
>>> Java simply does not allow to use a constructor on an enum (with a
>> reason).
>>
>
> Understood. That's why my example includes the getYamlValue() which pulls
> the enum from the HashMap.

I'm pleading guilty of not reading every single line of Java code ;-)

> I suppose I should have phrased my question like "is there a way I can use
> SnakeYaml Construct/Constructor/TypeDescription/Tag to invoke my
> getYamlValue() instead of enum.valueOf()?".

Now that's something that would interest me as well. I can see multiple
use cases with a mapping from string values to internal values - not
just enums but other data as well.
Reply all
Reply to author
Forward
0 new messages