JAXB allows to directly locate Enum instances from XML by using the @XMLEnum
annotation.
It seems that JAXB is case-sensitive when it comes to locating value from @XMLEnumValue
.
But I am facing a problem in which I need to locate Enum instance in a case-insensitive manner. Does JAXB in some way provide this functionality? Without this I am stuck with manually locating the Enum constant.
I can use XMLAdapter
for this, but becomes very tedious to maintain an adapter for each enum created.
EDIT:
Why do you have to locate the enum in a case-insensitive manner?
Because I am using xml to read configuration for my system and I don't want users to be restricted to fixed case. I hope that answers your question.
public class CaseInsensitiveEnumAdapter<E extends Enum<E>> extends XmlAdapter<String, E> {
private final Class<E> clazz;
public CaseInsensitiveEnumAdapter(Class<E> clazz) {
this.clazz = clazz;
}
@Override
public E unmarshal(String v) throws Exception {
return Enum.<E>valueOf(clazz, v.toUpperCase().trim());
}
@Override
public String marshal(E v) throws Exception {
return v.name();
}
}
As I require the .class
for an enum, I will have to create separate adapters for all enums.
Kind Mr. Narendra,
I came up with a solution based on regular expressions. The idea is to use pattern restriction with a regular expression capable of accepting any case combination. I created an example with an enumeration of three colors: green, red and blue. The following regular exception would accept both "GrEEn" and "gReeN" literals as valid values:
g|Gr|Re|Ee|En|N
Here under the example files:
Example XML-Schema
<xs:simpleType name="ColorType" final="restriction" >
<xs:restriction base="xs:string">
<xs:pattern value="g|Gr|Re|Ee|En|N" />
<xs:pattern value="r|Re|Ed|D" />
<xs:pattern value="b|Bl|Lu|Ue|E" />
</xs:restriction>
</xs:simpleType>
<xs:element name="SomeElement">
<xs:complexType>
<xs:sequence>
<xs:element name="Color" type="ColorType" />
</xs:sequence>
</xs:complexType>
</xs:element>
XML Case 1
<SomeElement>
<Color>GreEN</Color>
</SomeElement>
XML Case 2
<SomeElement>
<Color>gREen</Color>
</SomeElement>
JUnit
public class TestJaxb {
private static final String GREEN = "GREEN";
@Test
public void shouldParseCase1() throws JAXBException, MalformedURLException {
URL xmlUrl = // Load XML file 1
SomeElement someElement = parse(xmlUrl, SomeElement.class);
assertEquals(GREEN, someElement.getColor().toUpperCase());
}
@Test
public void shouldParseCase2() throws JAXBException, MalformedURLException {
URL xmlUrl = // Load XML file 2
SomeElement someElement = parse(xmlUrl, SomeElement.class);
assertEquals(GREEN, someElement.getColor().toUpperCase());
}
private <T> T parse(URL url, Class<T> clazz) throws JAXBException {
Unmarshaller unmarshaller = JAXBContext.newInstance(clazz).createUnmarshaller();
return clazz.cast(unmarshaller.unmarshal(url));
}
}
I realize that this makes it more difficult for the user of your XSD specification to understand which values are allowed in the enumeration, but maybe a comment would be enough for you.
The fact is that there is no other way that I've found to achieve this without actually altering JAXB code.
Hope this helps.
Best regards
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With