eclipse-ee4j / eclipselink

Eclipselink project
https://eclipse.dev/eclipselink/
Other
198 stars 168 forks source link

DynamicJAXB doesn't handle @XmlEnumValue() from XJC class #2272

Open timtatt opened 5 days ago

timtatt commented 5 days ago

Describe the bug When XJC generated enum literals differ from the original schema, DynamicJAXB does not marshal/unmarshal correctly

XSD: xmlenum-numbers.xsd

<xs:schema targetNamespace="myNamespace" xmlns:myns="myNamespace" xmlns:xs="http://www.w3.org/2001/XMLSchema"
    attributeFormDefault="qualified" elementFormDefault="qualified">

    <xs:element name="tax-record">
        <xs:complexType>
            <xs:sequence>
                <xs:element name="period" type="myns:period"/>
            </xs:sequence>
        </xs:complexType>
    </xs:element>

    <!-- This test contains exactly 6 enum values to test an ASM boundary case (ICONST) -->
    <xs:simpleType name="period">
        <xs:restriction base="xs:string">
            <xs:enumeration value="QTR1"/>
            <xs:enumeration value="QTR2"/>
        </xs:restriction>
    </xs:simpleType>

</xs:schema>

Given the above XSD, XJC will generated an enum like below

public class enum Period {
@XmlEnumValue("QTR1")
QTR_1("QTR1")
@XmlEnumValue("QTR2")
QTR_2("QTR2");

private final String value;

Period(String v) {
  value = v
};
}

When unmarshalling the below Xml, the Period enum is not being evaluated by Dynamic JAXBContext

<tax-record>
<period>QTR1</period>
</tax-record>

period attribute will show as null

To Reproduce Steps/resources to reproduce the behavior:

Expected behavior When marshalling enum with a differing 'value' from the literal, the value should be used rather than the literal.

XML

<tax-record>
<period>QTR1</period>
</tax-record>

Unmarshals to: TaxRecord:

And will marshal back into the same XML as above

Additional context Below is a test case which should pass

public void testXmlEnumWithNumbers() throws Exception {
        // Tests XmlEnum and XmlEnumValue

        InputStream inputStream = ClassLoader.getSystemResourceAsStream(RESOURCE_DIR + "xmlenum-numbers.xsd");
        jaxbContext = DynamicJAXBContextFactory.createContextFromXSD(inputStream, null, null, null);

        DynamicEntity taxRecord = jaxbContext.newDynamicEntity(PACKAGE + ".TaxRecord");
        assertNotNull("Could not create Dynamic Entity.", taxRecord);

        Object QTR_1 = jaxbContext.getEnumConstant(PACKAGE + ".Period", "QTR_1");
        assertNotNull("Could not find enum constant.", QTR_1);

        taxRecord.set("period", QTR_1);

        Document marshalDoc = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
        jaxbContext.createMarshaller().marshal(taxRecord, marshalDoc);

        assertEquals("QTR1", marshalDoc.getDocumentElement().getTextContent());
    }