Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Manipulate JAXB enum key names

Tags:

enums

xml

jaxb

xsd

xjc

the last days I was looking for an solution for my jaxb problem, but it was not successfully... So I hope that maybe someone here could help me.

The base is an xsd schema from an external partner that is as is, i.e. I can not change it. The classes are generated with xjc without problems, but the enums are not "java compatible". Some of the values are nummeric or alphanumeric so that it was neccessary to set the attribute typesafeEnumMemberName="generateName" in the binding.

Jaxb generates then the enum keys like VALUE_1, VALUE_2 and so on. My problem is now, that some of the enums have < 250 entries and only the javadoc of the entries says information about the value. That is not realy comfortable and can force errors because the value VALUE_1 of the following MandatType enum has the value "E" and not "1".... xsd:

<xsd:simpleType name="MandatType">
    <xsd:annotation>
        <xsd:documentation/>
    </xsd:annotation>
    <xsd:restriction base="xsd:string">
        <xsd:maxLength value="1"/>
        <xsd:minLength value="1"/>
        <xsd:enumeration value="E">
            <xsd:annotation>
                <xsd:documentation>Erinnerung</xsd:documentation>
            </xsd:annotation>
        </xsd:enumeration>
        <xsd:enumeration value="1">
            <xsd:annotation>
                <xsd:documentation>Klage</xsd:documentation>
            </xsd:annotation>
        </xsd:enumeration>
        <xsd:enumeration value="2">
            <xsd:annotation>
                <xsd:documentation>Beschaffung</xsd:documentation>
            </xsd:annotation>
        </xsd:enumeration>
        <xsd:enumeration value="Z">
            <xsd:annotation>
                <xsd:documentation>Storno</xsd:documentation>
             </xsd:annotation>
        </xsd:enumeration>
    </xsd:restriction>
</xsd:simpleType>

class:

@XmlType(name = "MandatType")
@XmlEnum
public enum MandatType {
    /**
     * Erinnerung 
     * 
     */
    @XmlEnumValue("E")
    VALUE_1("E"),

    /**
     * Klage
     * 
     */
    @XmlEnumValue("1")
    VALUE_2("1"),

    /**
     * Beschaffung
     * 
     */
    @XmlEnumValue("2")
    VALUE_3("2"),

    /**
     * Storno
     * 
     */
    @XmlEnumValue("Z")
    VALUE_Z("Z"),

    //...
}

The only solution I have found is to define for each enum value in the binding the enum key. But the problem is, that are round about 14.000 values! So does anyone an other ideo to solve that? Is it possible to define a method to override/change the enum value when xjc generates the classes? Or to use the xsd:documentation value for the keys of the enum?

Many thanks in advance Stephan

like image 294
slx Avatar asked Nov 23 '25 18:11

slx


1 Answers

It is possible to write your own JAXB plugin, which could then be used to incorporate arbitrary data to modify the generated code. This link has some pointers which you may explore for additional information.

Alternatively, you may consider something easier (in my opinion), and that is to refactor your XSD into something that would work with out of the box functionality.

If all you want is along these lines, to convert this:

    <xsd:enumeration value="E">
        <xsd:annotation>
            <xsd:documentation>Erinnerung</xsd:documentation>
        </xsd:annotation>
    </xsd:enumeration>

into this:

    <xsd:enumeration value="E">
        <xsd:annotation>
            <xsd:documentation>Erinnerung</xsd:documentation>
            <xsd:appinfo>
                <jaxb:typesafeEnumMember name="Erinnerung"/>
            </xsd:appinfo>              
        </xsd:annotation>
    </xsd:enumeration>

Then I would think basic XSLT skills should help you with this, better than writing a JAXB plugin, or using XSOM, etc. where 14000 or so shouldn't make a difference. Even if your schema is spread over hundreds of files, it would still be easier to just right a dumb XSLT that does one schema at a time, and then simply generate command lines for each file...

Here is a simple XSLT:

<xsl:stylesheet version="1.0" xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <xsl:template match="@*|node()">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
  </xsl:template>

    <xsl:template match="xsd:enumeration">
        <xsd:enumeration>
            <xsl:attribute name="value">
                <xsl:value-of select="@value"/>
            </xsl:attribute>
            <xsd:annotation>
                <xsl:copy-of select="xsd:annotation/xsd:documentation"/>
                <xsd:appinfo>
                    <jaxb:typesafeEnumMember>
                        <xsl:attribute name="name">
                             <xsl:value-of select="xsd:annotation/xsd:documentation"/>
                        </xsl:attribute>
                    </jaxb:typesafeEnumMember>
                </xsd:appinfo>                          
            </xsd:annotation>
        </xsd:enumeration>
    </xsl:template>
</xsl:stylesheet>

One could replace the simple documentation "dump" with a template call, which could process the text, or provide alternatives, or issue a message for certain conditions, etc.

The generated output might look like this:

<?xml version="1.0" encoding="utf-16"?>
<xsd:schema targetNamespace="http://tempuri.org/XMLSchema.xsd" elementFormDefault="qualified" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" xmlns="http://tempuri.org/XMLSchema.xsd" xmlns:xtm="http://paschidev.com/schemas/metadata/xtm">
    <xsd:simpleType name="MandatType">
        <xsd:annotation>
            <xsd:documentation/>
        </xsd:annotation>
        <xsd:restriction base="xsd:string">
            <xsd:maxLength value="1"/>
            <xsd:minLength value="1"/>
            <xsd:enumeration value="E">
                <xsd:annotation>
                    <xsd:documentation>Erinnerung</xsd:documentation>
                    <xsd:appinfo>
                        <jaxb:typesafeEnumMember name="Erinnerung"/>
                    </xsd:appinfo>
                </xsd:annotation>
            </xsd:enumeration>
            <xsd:enumeration value="1">
                <xsd:annotation>
                    <xsd:documentation>Klage</xsd:documentation>
                    <xsd:appinfo>
                        <jaxb:typesafeEnumMember name="Klage"/>
                    </xsd:appinfo>
                </xsd:annotation>
            </xsd:enumeration>
            <xsd:enumeration value="2">
                <xsd:annotation>
                    <xsd:documentation>Beschaffung</xsd:documentation>
                    <xsd:appinfo>
                        <jaxb:typesafeEnumMember name="Beschaffung"/>
                    </xsd:appinfo>
                </xsd:annotation>
            </xsd:enumeration>
            <xsd:enumeration value="Z">
                <xsd:annotation>
                    <xsd:documentation>Storno</xsd:documentation>
                    <xsd:appinfo>
                        <jaxb:typesafeEnumMember name="Storno"/>
                    </xsd:appinfo>
                </xsd:annotation>
            </xsd:enumeration>
        </xsd:restriction>
    </xsd:simpleType>
</xsd:schema>
like image 104
Petru Gardea Avatar answered Nov 28 '25 04:11

Petru Gardea



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!