/*
 * Copyright (c) 2011, 2021 Oracle and/or its affiliates. All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0 which is available at
 * http://www.eclipse.org/legal/epl-2.0,
 * or the Eclipse Distribution License v. 1.0 which is available at
 * http://www.eclipse.org/org/documents/edl-v10.php.
 *
 * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
 */

// Contributors:
//     rbarkhouse - 2.2 - initial implementation
package org.eclipse.persistence.testing.jaxb.dynamic;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.UndeclaredThrowableException;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Vector;

import jakarta.xml.bind.JAXBElement;
import jakarta.xml.bind.Marshaller;
import jakarta.xml.bind.Unmarshaller;
import javax.xml.datatype.DatatypeConstants;
import javax.xml.datatype.DatatypeFactory;
import javax.xml.namespace.QName;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamReader;
import javax.xml.transform.Source;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamSource;

import junit.framework.TestCase;

import org.eclipse.persistence.config.DescriptorCustomizer;
import org.eclipse.persistence.descriptors.ClassDescriptor;
import org.eclipse.persistence.descriptors.ClassExtractor;
import org.eclipse.persistence.dynamic.DynamicEntity;
import org.eclipse.persistence.internal.oxm.XMLConversionManager;
import org.eclipse.persistence.jaxb.JAXBContextFactory;
import org.eclipse.persistence.jaxb.dynamic.DynamicJAXBContext;
import org.eclipse.persistence.jaxb.dynamic.DynamicJAXBContextFactory;
import org.eclipse.persistence.mappings.transformers.AttributeTransformerAdapter;
import org.eclipse.persistence.mappings.transformers.FieldTransformerAdapter;
import org.eclipse.persistence.oxm.XMLConstants;
import org.eclipse.persistence.oxm.XMLDescriptor;
import org.eclipse.persistence.oxm.XMLField;
import org.eclipse.persistence.oxm.mappings.XMLDirectMapping;
import org.eclipse.persistence.sessions.Record;
import org.eclipse.persistence.sessions.Session;
import org.eclipse.persistence.testing.jaxb.dynamic.util.Computer;
import org.eclipse.persistence.testing.jaxb.dynamic.util.ComputerAdapter;
import org.eclipse.persistence.testing.jaxb.dynamic.util.LinkAdapter;
import org.eclipse.persistence.testing.jaxb.dynamic.util.LinkAdapterString;
import org.w3c.dom.CDATASection;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.xml.sax.EntityResolver;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

public class DynamicJAXBFromOXMTestCases extends TestCase {

    private DynamicJAXBContext jaxbContext;

    public DynamicJAXBFromOXMTestCases(String name) throws Exception {
        super(name);
    }

    @Override
    public String getName() {
        return "Dynamic JAXB: OXM: " + super.getName();
    }

    // Standard OXM Annotation tests
    // ====================================================================

    public void testXmlSchemaQualified() throws Exception {
        ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
        InputStream iStream = classLoader.getResourceAsStream(XMLSCHEMA_QUALIFIED);
        if (iStream == null) {
            fail("Couldn't load metadata file [" + XMLSCHEMA_QUALIFIED + "]");
        }

        Map<String, Object> properties = new HashMap<String, Object>();
        properties.put(JAXBContextFactory.ECLIPSELINK_OXM_XML_KEY, iStream);

        jaxbContext = DynamicJAXBContextFactory.createContextFromOXM(classLoader, properties);

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

        person.set("id", 456);
        person.set("name", "Bob Dobbs");
        person.set("salary", 45000.00);

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

        // Make sure "targetNamespace" was interpreted properly.
        Element element = marshalDoc.getDocumentElement();
        assertEquals("Target Namespace was not set as expected.", "mynamespace", element.getNamespaceURI());

        // Make sure "elementFormDefault" was interpreted properly.
        // elementFormDefault=qualified, so the root node, the
        // root node's attribute, and the child node should all have a prefix.
        assertNotNull("Root node did not have namespace prefix as expected.", element.getPrefix());

        Node attr = element.getAttributeNodeNS("mynamespace", "id");
        assertNotNull("Attribute did not have namespace prefix as expected.", attr.getPrefix());

        Node childNode = element.getElementsByTagNameNS("mynamespace", "salary").item(0);
        assertNotNull("Child node did not have namespace prefix as expected.", childNode.getPrefix());
    }

    public void testXmlSchemaUnqualified() throws Exception {
        ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
        InputStream iStream = classLoader.getResourceAsStream(XMLSCHEMA_UNQUALIFIED);
        if (iStream == null) {
            fail("Couldn't load metadata file [" + XMLSCHEMA_UNQUALIFIED + "]");
        }

        Map<String, Object> properties = new HashMap<String, Object>();
        properties.put(JAXBContextFactory.ECLIPSELINK_OXM_XML_KEY, iStream);

        jaxbContext = DynamicJAXBContextFactory.createContextFromOXM(classLoader, properties);

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

        person.set("id", 456);
        person.set("name", "Bob Dobbs");
        person.set("salary", 45000.00);

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

        // Make sure "targetNamespace" was interpreted properly.
        Element element = marshalDoc.getDocumentElement();
        assertEquals("Target Namespace was not set as expected.", "mynamespace", element.getNamespaceURI());

        // Make sure "elementFormDefault" was interpreted properly.
        // elementFormDefault=unqualified, so the root node should have a prefix
        // but the root node's attribute and child node should not.
        assertNotNull("Root node did not have namespace prefix as expected.", element.getPrefix());

        Node attr = element.getAttributeNode("id");
        assertNull("Attribute should not have namespace prefix (" + attr.getPrefix() + ").", attr.getPrefix());

        Node childNode = element.getElementsByTagName("salary").item(0);
        assertNull("Child node should not have namespace prefix.", childNode.getPrefix());
    }

    public void testXmlSchemaDefaults() throws Exception {
        ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
        InputStream iStream = classLoader.getResourceAsStream(XMLSCHEMA_DEFAULTS);
        if (iStream == null) {
            fail("Couldn't load metadata file [" + XMLSCHEMA_DEFAULTS + "]");
        }
        HashMap<String, Source> metadataSourceMap = new HashMap<String, Source>();
        // Testing defaults, so don't specify a package name (default package)
        metadataSourceMap.put("", new StreamSource(iStream));

        Map<String, Object> properties = new HashMap<String, Object>();
        properties.put(JAXBContextFactory.ECLIPSELINK_OXM_XML_KEY, metadataSourceMap);

        jaxbContext = DynamicJAXBContextFactory.createContextFromOXM(classLoader, properties);

        DynamicEntity person = jaxbContext.newDynamicEntity(PERSON);
        assertNotNull("Could not create Dynamic Entity.", person);

        person.set("id", 456);
        person.set("name", "Bob Dobbs");
        person.set("salary", 45000.00);

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

        // "targetNamespace" should be null by default
        Element element = marshalDoc.getDocumentElement();
        assertNull("Target Namespace was not null as expected.", element.getNamespaceURI());

        // Make sure "elementFormDefault" was interpreted properly.
        // When unset, no namespace qualification is done.
        assertNull("Root node should not have namespace prefix.", element.getPrefix());

        Node attr = element.getAttributeNode("id");
        assertNull("Attribute should not have namespace prefix.", attr.getPrefix());

        Node childNode = element.getElementsByTagName("salary").item(0);
        assertNull("Child node should not have namespace prefix.", childNode.getPrefix());
    }

    public void testXmlRootElement() throws Exception {
        ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
        InputStream iStream = classLoader.getResourceAsStream(XMLROOTELEMENT);
        if (iStream == null) {
            fail("Couldn't load metadata file [" + XMLROOTELEMENT + "]");
        }

        Map<String, Object> properties = new HashMap<String, Object>();
        properties.put(JAXBContextFactory.ECLIPSELINK_OXM_XML_KEY, iStream);

        jaxbContext = DynamicJAXBContextFactory.createContextFromOXM(classLoader, properties);

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

        person.set("name", "Bob Dobbs");

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

        Node node = marshalDoc.getChildNodes().item(0);

        assertEquals("Root element was not 'individuo' as expected.", "individuo", node.getLocalName());
    }

    public void testXmlType() throws Exception {
        ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
        InputStream iStream = classLoader.getResourceAsStream(XMLTYPE);
        if (iStream == null) {
            fail("Couldn't load metadata file [" + XMLTYPE + "]");
        }

        Map<String, Object> properties = new HashMap<String, Object>();
        properties.put(JAXBContextFactory.ECLIPSELINK_OXM_XML_KEY, iStream);

        jaxbContext = DynamicJAXBContextFactory.createContextFromOXM(classLoader, properties);

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

        person.set("email", "bdobbs@subgenius.com");
        person.set("lastName", "Dobbs");
        person.set("id", 678);
        person.set("phoneNumber", "212-555-8282");
        person.set("firstName", "Bob");

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

        // Test that XmlType.propOrder was interpreted properly
        Node node = marshalDoc.getDocumentElement().getChildNodes().item(0);
        assertNotNull("Node was null.", node);
        assertEquals("Unexpected node.", "id", node.getLocalName());

        node = marshalDoc.getDocumentElement().getChildNodes().item(1);
        assertNotNull("Node was null.", node);
        assertEquals("Unexpected node.", "firstName", node.getLocalName());

        node = marshalDoc.getDocumentElement().getChildNodes().item(2);
        assertNotNull("Node was null.", node);
        assertEquals("Unexpected node.", "lastName", node.getLocalName());

        node = marshalDoc.getDocumentElement().getChildNodes().item(3);
        assertNotNull("Node was null.", node);
        assertEquals("Unexpected node.", "phoneNumber", node.getLocalName());

        node = marshalDoc.getDocumentElement().getChildNodes().item(4);
        assertNotNull("Node was null.", node);
        assertEquals("Unexpected node.", "email", node.getLocalName());
    }

    public void testXmlAttribute() throws Exception {
        ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
        InputStream iStream = classLoader.getResourceAsStream(XMLATTRIBUTE);
        if (iStream == null) {
            fail("Couldn't load metadata file [" + XMLATTRIBUTE + "]");
        }

        Map<String, Object> properties = new HashMap<String, Object>();
        properties.put(JAXBContextFactory.ECLIPSELINK_OXM_XML_KEY, iStream);

        jaxbContext = DynamicJAXBContextFactory.createContextFromOXM(classLoader, properties);

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

        person.set("id", 777);

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

        Node node = marshalDoc.getChildNodes().item(0);

        if (node.getAttributes() == null || node.getAttributes().getNamedItemNS("mynamespace", "id") == null) {
            fail("Attribute not present.");
        }
    }

    public void testXmlElement() throws Exception {
        ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
        InputStream iStream = classLoader.getResourceAsStream(XMLELEMENT);
        if (iStream == null) {
            fail("Couldn't load metadata file [" + XMLELEMENT + "]");
        }

        Map<String, Object> properties = new HashMap<String, Object>();
        properties.put(JAXBContextFactory.ECLIPSELINK_OXM_XML_KEY, iStream);

        jaxbContext = DynamicJAXBContextFactory.createContextFromOXM(classLoader, properties);

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

        person.set("type", "O+");

        ArrayList<String> nicknames;

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

        Node node = marshalDoc.getDocumentElement();

        assertNotNull("Element not present.", node.getChildNodes());

        String elemName = node.getChildNodes().item(0).getNodeName();
        assertEquals("Element not present.", "type", elemName);
    }

    public void testXmlList() throws Exception {
        // Also tests collection of XmlElement
        ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
        InputStream iStream = classLoader.getResourceAsStream(XMLLIST);
        if (iStream == null) {
            fail("Couldn't load metadata file [" + XMLLIST + "]");
        }

        Map<String, Object> properties = new HashMap<String, Object>();
        properties.put(JAXBContextFactory.ECLIPSELINK_OXM_XML_KEY, iStream);

        jaxbContext = DynamicJAXBContextFactory.createContextFromOXM(classLoader, properties);

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

        person.set("name", "Richard Nixon");

        ArrayList<String> nicks = new ArrayList<String>();
        nicks.add("Tricky Dick");
        nicks.add("Iron Butt");
        person.set("nicknames", nicks);

        ArrayList<String> emails = new ArrayList<String>();
        emails.add("nixon.richard@whitehouse.gov");
        emails.add("rnixon1913@aol.com");
        person.set("emails", emails);

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

        int numNicks = marshalDoc.getElementsByTagName("nicknames").getLength();
        assertEquals("Incorrect number of nicknames.", 2, numNicks);

        int numEmails = marshalDoc.getElementsByTagName("emails").getLength();
        assertEquals("Incorrect number of emails.", 1, numEmails);

        DynamicEntity readPerson = (DynamicEntity) jaxbContext.createUnmarshaller().unmarshal(marshalDoc);
        assertEquals("Incorrect number of nicknames.", 2, ((ArrayList) person.get("nicknames")).size());
        assertEquals("Incorrect number of emails.", 2, ((ArrayList) person.get("emails")).size());
    }

    public void testXmlValue() throws Exception {
        ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
        InputStream iStream = classLoader.getResourceAsStream(XMLVALUE);
        if (iStream == null) {
            fail("Couldn't load metadata file [" + XMLVALUE + "]");
        }

        Map<String, Object> properties = new HashMap<String, Object>();
        properties.put(JAXBContextFactory.ECLIPSELINK_OXM_XML_KEY, iStream);

        jaxbContext = DynamicJAXBContextFactory.createContextFromOXM(classLoader, properties);

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

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

        salary.set("amount", new BigDecimal(75100));

        person.set("name", "Bob Dobbs");
        person.set("salary", salary);

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

        // Nothing to really test, XmlValue isn't represented in an instance doc.
    }

    public void testXmlAnyElement() throws Exception {
        ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
        InputStream iStream = classLoader.getResourceAsStream(XMLANYELEMENT);
        if (iStream == null) {
            fail("Couldn't load metadata file [" + XMLANYELEMENT + "]");
        }

        Map<String, Object> properties = new HashMap<String, Object>();
        properties.put(JAXBContextFactory.ECLIPSELINK_OXM_XML_KEY, iStream);

        jaxbContext = DynamicJAXBContextFactory.createContextFromOXM(classLoader, properties);

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

        person.set("name", "Bob Dobbs");
        person.set("any", "StringValue");

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

        Node node = marshalDoc.getDocumentElement();

        assertTrue("Any element not found.", node.getChildNodes().item(1).getNodeType() == Node.TEXT_NODE);
    }

    public void testXmlAnyAttribute() throws Exception {
        ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
        InputStream iStream = classLoader.getResourceAsStream(XMLANYATTRIBUTE);
        if (iStream == null) {
            fail("Couldn't load metadata file [" + XMLANYATTRIBUTE + "]");
        }

        Map<String, Object> properties = new HashMap<String, Object>();
        properties.put(JAXBContextFactory.ECLIPSELINK_OXM_XML_KEY, iStream);

        jaxbContext = DynamicJAXBContextFactory.createContextFromOXM(classLoader, properties);

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

        Map<QName, Object> otherAttributes = new HashMap<QName, Object>();
        otherAttributes.put(new QName("foo"), new BigDecimal(1234));
        otherAttributes.put(new QName("bar"), Boolean.FALSE);

        person.set("name", "Bob Dobbs");
        person.set("otherAttributes", otherAttributes);

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

        Node node = marshalDoc.getDocumentElement();
        Node otherAttributesNode = node.getAttributes().getNamedItem("foo");
        assertNotNull("'foo' attribute not found.", otherAttributesNode);
        otherAttributesNode = node.getAttributes().getNamedItem("bar");
        assertNotNull("'bar' attribute not found.", otherAttributesNode);
    }

    public void testXmlMixed() throws Exception {
        ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
        InputStream iStream = classLoader.getResourceAsStream(XMLMIXED);
        if (iStream == null) {
            fail("Couldn't load metadata file [" + XMLMIXED + "]");
        }

        Map<String, Object> properties = new HashMap<String, Object>();
        properties.put(JAXBContextFactory.ECLIPSELINK_OXM_XML_KEY, iStream);

        jaxbContext = DynamicJAXBContextFactory.createContextFromOXM(classLoader, properties);

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

        person.set("name", "Bob Dobbs");

        ArrayList list = new ArrayList();
        list.add("Hello ");
        list.add(new JAXBElement<String>(new QName("myNamespace", "title"), String.class, person.getClass(), "MR"));
        list.add(new JAXBElement<String>(new QName("myNamespace", "name"), String.class, person.getClass(), "Bob Dobbs"));
        list.add(", your point balance is ");
        list.add(new JAXBElement<BigInteger>(new QName("myNamespace", "rewardPoints"), BigInteger.class, person.getClass(), BigInteger.valueOf(175)));
        list.add("Visit www.rewards.com!");
        person.set("mixed", list);

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

        Node node = marshalDoc.getDocumentElement();

        assertEquals("Unexpected number of elements.", 7, node.getChildNodes().getLength());
    }

    public void testXmlId() throws Exception {
        // Tests both XmlId and XmlIdRef
        ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
        InputStream iStream = classLoader.getResourceAsStream(XMLID);
        if (iStream == null) {
            fail("Couldn't load metadata file [" + XMLID + "]");
        }

        Map<String, Object> properties = new HashMap<String, Object>();
        properties.put(JAXBContextFactory.ECLIPSELINK_OXM_XML_KEY, iStream);

        jaxbContext = DynamicJAXBContextFactory.createContextFromOXM(classLoader, properties);

        DynamicEntity data = jaxbContext.newDynamicEntity(PACKAGE + "." + DATA);
        assertNotNull("Could not create Dynamic Entity.", data);
        DynamicEntity person = jaxbContext.newDynamicEntity(PACKAGE + "." + PERSON);
        assertNotNull("Could not create Dynamic Entity.", person);
        DynamicEntity company = jaxbContext.newDynamicEntity(PACKAGE + "." + COMPANY);
        assertNotNull("Could not create Dynamic Entity.", company);

        company.set("name", "ACME International");
        company.set("address", "165 Main St, Anytown US, 93012");
        company.set("id", Integer.valueOf(882));

        person.set("name", "Bob Dobbs");
        person.set("company", company);

        data.set("person", person);
        data.set("company", company);

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

        // 'person' node
        Node pNode = marshalDoc.getDocumentElement().getChildNodes().item(0);
        // 'company' node
        Node cNode = pNode.getChildNodes().item(1);

        // If IDREF worked properly, the company element should only contain the id of the company object
        assertEquals("'company' has unexpected number of child nodes.", 1, cNode.getChildNodes().getLength());
    }

    public void testXmlElements() throws Exception {
        ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
        InputStream iStream = classLoader.getResourceAsStream(XMLELEMENTS);
        if (iStream == null) {
            fail("Couldn't load metadata file [" + XMLELEMENTS + "]");
        }

        Map<String, Object> properties = new HashMap<String, Object>();
        properties.put(JAXBContextFactory.ECLIPSELINK_OXM_XML_KEY, iStream);

        jaxbContext = DynamicJAXBContextFactory.createContextFromOXM(classLoader, properties);

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

        ArrayList list = new ArrayList(1);
        list.add("BOB");
        person.set("items", list);

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

        Node node = marshalDoc.getDocumentElement().getChildNodes().item(0);

        assertEquals("Unexpected element name.", "name", node.getNodeName());

        person = jaxbContext.newDynamicEntity(PACKAGE + "." + PERSON);
        list = new ArrayList(1);
        list.add(328763);
        person.set("items", list);
        marshalDoc = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
        jaxbContext.createMarshaller().marshal(person, marshalDoc);
        node = marshalDoc.getDocumentElement().getChildNodes().item(0);

        assertEquals("Unexpected element name.", "referenceNumber", node.getNodeName());
    }

    public void testXmlElementRef() throws Exception {
        ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
        InputStream iStream = classLoader.getResourceAsStream(XMLELEMENTREF);
        if (iStream == null) {
            fail("Couldn't load metadata file [" + XMLELEMENTREF + "]");
        }

        Map<String, Object> properties = new HashMap<String, Object>();
        properties.put(JAXBContextFactory.ECLIPSELINK_OXM_XML_KEY, iStream);

        jaxbContext = DynamicJAXBContextFactory.createContextFromOXM(classLoader, properties);

        DynamicEntity person = jaxbContext.newDynamicEntity(PACKAGE + "." + PERSON);
        assertNotNull("Could not create Dynamic Entity.", person);
        person.set("name", "Jim Watson");

        DynamicEntity phone1 = jaxbContext.newDynamicEntity(PACKAGE + "." + PHONE);
        phone1.set("id", 111);
        phone1.set("number", "118-123-1124");

        DynamicEntity phone2 = jaxbContext.newDynamicEntity(PACKAGE + "." + PHONE);
        phone2.set("id", 222);
        phone2.set("number", "623-121-7425");

        ArrayList<DynamicEntity> phones = new ArrayList<DynamicEntity>();
        phones.add(phone1);
        phones.add(phone2);
        person.set("phones", phones);

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

        Node node = marshalDoc.getDocumentElement().getChildNodes().item(1);
        assertEquals("Element wrapper not written as expected.", "gsm_phones", node.getNodeName());

        DynamicEntity readPerson = (DynamicEntity) jaxbContext.createUnmarshaller().unmarshal(marshalDoc);

        ArrayList<DynamicEntity> l = readPerson.get("phones");
        assertEquals("Phones not unmarshalled as expected.", 111, ((Number) (l.get(0).get("id"))).intValue());
    }

    public void testXmlSchemaType() throws Exception {
        ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
        InputStream iStream = classLoader.getResourceAsStream(XMLSCHEMATYPE);
        if (iStream == null) {
            fail("Couldn't load metadata file [" + XMLSCHEMATYPE + "]");
        }

        Map<String, Object> properties = new HashMap<String, Object>();
        properties.put(JAXBContextFactory.ECLIPSELINK_OXM_XML_KEY, iStream);

        jaxbContext = DynamicJAXBContextFactory.createContextFromOXM(classLoader, properties);

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

        person.set("dateOfBirth", DatatypeFactory.newInstance().newXMLGregorianCalendarDate(1976, 02, 17, DatatypeConstants.FIELD_UNDEFINED));

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

        Node node = marshalDoc.getDocumentElement().getChildNodes().item(0);

        assertEquals("Unexpected date value.", "1976-02-17", node.getTextContent());
    }

    public void testXmlEnum() throws Exception {
        ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
        InputStream iStream = classLoader.getResourceAsStream(XMLENUM);
        if (iStream == null) {
            fail("Couldn't load metadata file [" + XMLENUM + "]");
        }

        Map<String, Object> properties = new HashMap<String, Object>();
        properties.put(JAXBContextFactory.ECLIPSELINK_OXM_XML_KEY, iStream);

        jaxbContext = DynamicJAXBContextFactory.createContextFromOXM(classLoader, properties);

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

        Object nConst = jaxbContext.getEnumConstant(PACKAGE + "." + COMPASS_DIRECTION, "N");
        assertNotNull("Could not find enum constant.", nConst);

        person.set("quadrant", nConst);

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

        Node node = marshalDoc.getDocumentElement().getChildNodes().item(0);
        assertEquals("Enum not written as expected.", "NORTH", node.getTextContent());
    }

    public void testXmlEnumError() throws Exception {
        // Tests XmlEnum and XmlEnumValue
        ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
        InputStream iStream = classLoader.getResourceAsStream(XMLENUM);
        if (iStream == null) {
            fail("Couldn't load metadata file [" + XMLENUM + "]");
        }

        Map<String, Object> properties = new HashMap<String, Object>();
        properties.put(JAXBContextFactory.ECLIPSELINK_OXM_XML_KEY, iStream);

        jaxbContext = DynamicJAXBContextFactory.createContextFromOXM(classLoader, properties);

        Exception caughtException = null;
        try {
            Object NORTHWEST = jaxbContext.getEnumConstant(PACKAGE + "." + COMPASS_DIRECTION, "NORTHWEST");
        } catch (Exception e) {
            caughtException = e;
        }

        assertNotNull("Expected exception was not thrown.", caughtException);
    }

    public void testXmlElementDecl() throws Exception {
        // Also tests XmlRegistry
        ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
        InputStream iStream = classLoader.getResourceAsStream(XMLELEMENTDECL);
        if (iStream == null) {
            fail("Couldn't load metadata file [" + XMLELEMENTDECL + "]");
        }

        Map<String, Object> properties = new HashMap<String, Object>();
        properties.put(JAXBContextFactory.ECLIPSELINK_OXM_XML_KEY, iStream);

        jaxbContext = DynamicJAXBContextFactory.createContextFromOXM(classLoader, properties);

        DynamicEntity individuo = jaxbContext.newDynamicEntity(PACKAGE + "." + PERSON);
        assertNotNull("Could not create Dynamic Entity.", individuo);
        individuo.set("name", "Bob Dobbs");

        QName individuoQName = new QName(PACKAGE, INDIVIDUO);

        JAXBElement<DynamicEntity> individuoElement = new JAXBElement<DynamicEntity>(individuoQName, DynamicEntity.class, individuo);
        individuoElement.setValue(individuo);

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

        Node node = marshalDoc.getChildNodes().item(0);

        assertEquals("Root element was not 'individuo' as expected.", "individuo", node.getLocalName());
    }

    // Other tests
    // ====================================================================

    public void testSubstitutionGroupsMarshal() throws Exception {
        try {
            ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
            InputStream iStream = classLoader.getResourceAsStream(SUBSTITUTION);
            if (iStream == null) {
                fail("Couldn't load metadata file [" + SUBSTITUTION + "]");
            }

            Map<String, Object> properties = new HashMap<String, Object>();
            properties.put(JAXBContextFactory.ECLIPSELINK_OXM_XML_KEY, iStream);

            jaxbContext = DynamicJAXBContextFactory.createContextFromOXM(classLoader, properties);

            QName personQName = new QName("myNamespace", "person");
            DynamicEntity person = jaxbContext.newDynamicEntity("myNamespace" + "." + PERSON);
            JAXBElement<DynamicEntity> personElement = new JAXBElement<DynamicEntity>(personQName, DynamicEntity.class, person);
            personElement.setValue(person);

            QName nameQName = new QName("myNamespace", "name");
            JAXBElement<String> nameElement = new JAXBElement<String>(nameQName, String.class, "Marty Friedman");

            person.set("name", nameElement);

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

            Node node1 = marshalDoc.getDocumentElement();
            assertEquals("Incorrect element name: ", "person", node1.getLocalName());

            Node node2 = node1.getFirstChild();
            assertEquals("Incorrect element name: ", "name", node2.getLocalName());

            // ====================================================================

            QName personneQName = new QName("myNamespace", "personne");
            DynamicEntity personne = jaxbContext.newDynamicEntity("myNamespace" + "." + PERSON);
            JAXBElement<DynamicEntity> personneElement = new JAXBElement<DynamicEntity>(personneQName, DynamicEntity.class, personne);
            personneElement.setValue(personne);

            QName nomQName = new QName("myNamespace", "nom");
            JAXBElement<String> nomElement = new JAXBElement<String>(nomQName, String.class, "Marty Friedman");

            personne.set("name", nomElement);

            Document marshalDoc2 = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
            jaxbContext.createMarshaller().marshal(personneElement, marshalDoc2);

            Node node3 = marshalDoc2.getDocumentElement();
            assertEquals("Incorrect element name: ", "personne", node3.getLocalName());

            Node node4 = node3.getFirstChild();
            assertEquals("Incorrect element name: ", "nom", node4.getLocalName());
        } catch (UndeclaredThrowableException e) {
            if (e.getUndeclaredThrowable() instanceof NoSuchMethodException) {
                // We will get NoSuchMethod: XmlElementRef.required() if not running JAXB 2.2
                // or greater, so just pass in this case.
                assertTrue(true);
            }
        }
    }

    public void testSubstitutionGroupsUnmarshal() throws Exception {
        try {
            ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
            InputStream iStream = classLoader.getResourceAsStream(SUBSTITUTION);
            if (iStream == null) {
                fail("Couldn't load metadata file [" + SUBSTITUTION + "]");
            }

            Map<String, Object> properties = new HashMap<String, Object>();
            properties.put(JAXBContextFactory.ECLIPSELINK_OXM_XML_KEY, iStream);

            jaxbContext = DynamicJAXBContextFactory.createContextFromOXM(classLoader, properties);

            InputStream xmlStream = ClassLoader.getSystemResourceAsStream(PERSON_XML);
            JAXBElement person = (JAXBElement) jaxbContext.createUnmarshaller().unmarshal(xmlStream);
            assertEquals("Element was not substituted properly: ", new QName("myNamespace", "person"), person.getName());
            JAXBElement name = ((DynamicEntity) person.getValue()).get("name");
            assertEquals("Element was not substituted properly: ", new QName("myNamespace", "name"), name.getName());

            // ====================================================================

            InputStream xmlStream2 = ClassLoader.getSystemResourceAsStream(PERSONNE_XML);
            JAXBElement person2 = (JAXBElement) jaxbContext.createUnmarshaller().unmarshal(xmlStream2);
            assertEquals("Element was not substituted properly: ", new QName("myNamespace", "personne"), person2.getName());
            JAXBElement name2 = ((DynamicEntity) person2.getValue()).get("name");
            assertEquals("Element was not substituted properly: ", new QName("myNamespace", "nom"), name2.getName());
        } catch (UndeclaredThrowableException e) {
            if (e.getUndeclaredThrowable() instanceof NoSuchMethodException) {
                // We will get NoSuchMethod: XmlElementRef.required() if not running JAXB 2.2
                // or greater, so just pass in this case.
                assertTrue(true);
            }
        }
    }

    public void testTypePreservation() throws Exception {
        ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
        InputStream iStream = classLoader.getResourceAsStream(DATATYPES);
        if (iStream == null) {
            fail("Couldn't load metadata file [" + DATATYPES + "]");
        }
        HashMap<String, Source> metadataSourceMap = new HashMap<String, Source>();
        // Testing defaults, so don't specify a package name (default package)
        metadataSourceMap.put("", new StreamSource(iStream));

        Map<String, Object> properties = new HashMap<String, Object>();
        properties.put(JAXBContextFactory.ECLIPSELINK_OXM_XML_KEY, metadataSourceMap);

        jaxbContext = DynamicJAXBContextFactory.createContextFromOXM(classLoader, properties);

        DynamicEntity person = jaxbContext.newDynamicEntity(PERSON);
        assertNotNull("Could not create Dynamic Entity.", person);

        person.set("id", 456);
        person.set("name", "Bob Dobbs");
        ArrayList payments = new ArrayList();
        payments.add(4150.00d);
        payments.add(4150.00d);
        payments.add(387.22d);
        person.set("payments", payments);

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

        DynamicEntity readPerson = (DynamicEntity) jaxbContext.createUnmarshaller().unmarshal(marshalDoc);

        assertEquals("Property type was not preserved during unmarshal.", Integer.class, readPerson.<Object>get("id").getClass());
        ArrayList readPayments = readPerson.get("payments");
        assertEquals("Property type was not preserved during unmarshal.", Double.class, readPayments.get(0).getClass());
    }

    // MOXy Extensions tests
    // ====================================================================

    public void testXmlReadOnly() throws Exception {
        ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
        InputStream iStream = classLoader.getResourceAsStream(XMLREADONLY);
        if (iStream == null) {
            fail("Couldn't load metadata file [" + XMLREADONLY + "]");
        }

        Map<String, Object> properties = new HashMap<String, Object>();
        properties.put(JAXBContextFactory.ECLIPSELINK_OXM_XML_KEY, iStream);

        jaxbContext = DynamicJAXBContextFactory.createContextFromOXM(classLoader, properties);

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

        person.set("name", "Lisa Nova");
        person.set("sin", "272762998");

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

        // Ensure that the 'sin' element was not written
        int occurancesOfSin = marshalDoc.getElementsByTagName("sin").getLength();
        assertEquals("Read-only element 'sin' was written to XML.", 0, occurancesOfSin);
    }

    public void testXmlWriteOnly() throws Exception {
        ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
        InputStream iStream = classLoader.getResourceAsStream(XMLWRITEONLY);
        if (iStream == null) {
            fail("Couldn't load metadata file [" + XMLWRITEONLY + "]");
        }

        Map<String, Object> properties = new HashMap<String, Object>();
        properties.put(JAXBContextFactory.ECLIPSELINK_OXM_XML_KEY, iStream);

        jaxbContext = DynamicJAXBContextFactory.createContextFromOXM(classLoader, properties);

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

        person.set("name", "Lisa Nova");
        person.set("last-modified", System.currentTimeMillis());

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

        // Ensure that the 'last-modified' element was not read
        DynamicEntity readPerson = (DynamicEntity) jaxbContext.createUnmarshaller().unmarshal(marshalDoc);
        assertNull("Write-only element 'last-modified' was read from XML.", readPerson.get("last-modified"));
    }

    public void testXmlCDATA() throws Exception {
        ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
        InputStream iStream = classLoader.getResourceAsStream(XMLCDATA);
        if (iStream == null) {
            fail("Couldn't load metadata file [" + XMLCDATA + "]");
        }

        Map<String, Object> properties = new HashMap<String, Object>();
        properties.put(JAXBContextFactory.ECLIPSELINK_OXM_XML_KEY, iStream);

        jaxbContext = DynamicJAXBContextFactory.createContextFromOXM(classLoader, properties);

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

        person.set("characterData", "JKSGSIU&^@#bgr8736JGHYXC><#*&6JHGS");

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

        // Ensure that a CDATA node was written out
        Node node = marshalDoc.getChildNodes().item(0).getFirstChild().getFirstChild();
        assertTrue("Element contents did not contain expected ![CDATA[]].", node instanceof CDATASection);
    }

    public void testXmlPath() throws Exception {
        ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
        InputStream iStream = classLoader.getResourceAsStream(XMLPATH);
        if (iStream == null) {
            fail("Couldn't load metadata file [" + XMLPATH + "]");
        }

        Map<String, Object> properties = new HashMap<String, Object>();
        properties.put(JAXBContextFactory.ECLIPSELINK_OXM_XML_KEY, iStream);

        jaxbContext = DynamicJAXBContextFactory.createContextFromOXM(classLoader, properties);

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

        person.set("name", "Lisa Nova");

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

        String name = jaxbContext.getValueByXPath(person, "contact-info/personal-info/name/text()", null, String.class);
        assertNotNull("'name' element was not found at the specified XPath.", name);
    }

    public void testXmlNullPolicy() throws Exception {
        ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
        InputStream iStream = classLoader.getResourceAsStream(XMLNULLPOLICY);
        if (iStream == null) {
            fail("Couldn't load metadata file [" + XMLNULLPOLICY + "]");
        }

        Map<String, Object> properties = new HashMap<String, Object>();
        properties.put(JAXBContextFactory.ECLIPSELINK_OXM_XML_KEY, iStream);

        jaxbContext = DynamicJAXBContextFactory.createContextFromOXM(classLoader, properties);

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

        // First test marshaling
        // No fields are set in the Person, so we should see
        //    info1 - written as empty element
        //    info2 - absent element (should not appear)
        //    info3 - written with xsi:nil="true"
        Document marshalDoc = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
        jaxbContext.createMarshaller().marshal(person, marshalDoc);

        Node info1Node = marshalDoc.getElementsByTagName("write1").item(0);
        assertTrue("'write1' null policy was not applied during marshal.",
                info1Node.getAttributes().getLength() == 0 && info1Node.getChildNodes().getLength() == 0);

        Node info2Node = marshalDoc.getElementsByTagName("write2").item(0);
        assertNull("'write2' null policy was not applied during marshal.", info2Node);

        Node info3Node = marshalDoc.getElementsByTagName("write3").item(0);
        assertNotNull("'write3' null policy was not applied during marshal.",
                info3Node.getAttributes().getNamedItemNS(javax.xml.XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI, XMLConstants.SCHEMA_NIL_ATTRIBUTE));

        // Now test unmarshal
        InputStream is = ClassLoader.getSystemResourceAsStream(XMLNULLPOLICY_INSTANCE);
        DynamicEntity readPerson = (DynamicEntity) jaxbContext.createUnmarshaller().unmarshal(is);

        assertNull("'read1' should have been null in the object.", readPerson.get("read1"));
        assertNull("'read2' should have been null in the object.", readPerson.get("read2"));
        assertNull("'read3' should have been null in the object.", readPerson.get("read3"));
        assertNull("'read4' should have been null in the object.", readPerson.get("read4"));

        assertNull("'read5' should have been null in the object.", readPerson.get("read5"));
        assertNotNull("'read6' should have been empty Address the object.", readPerson.get("read6"));
        assertNull("'read7' should have been null in the object.", readPerson.get("read7"));
        assertNull("'read8' should have been null in the object.", readPerson.get("read8"));

        assertEquals("'read9' should have been empty String in the object.", "", readPerson.get("read9"));
        assertEquals("'read10' should have been empty String in the object.", "", readPerson.get("read10"));
        assertNull("'read11' should have been null in the object.", readPerson.get("read11"));
        assertNull("'read12' should have been null in the object.", readPerson.get("read12"));
    }

    public void testXmlProperties() throws Exception {
        ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
        InputStream iStream = classLoader.getResourceAsStream(XMLPROPERTIES);
        if (iStream == null) {
            fail("Couldn't load metadata file [" + XMLPROPERTIES + "]");
        }

        Map<String, Object> properties = new HashMap<String, Object>();
        properties.put(JAXBContextFactory.ECLIPSELINK_OXM_XML_KEY, iStream);

        jaxbContext = DynamicJAXBContextFactory.createContextFromOXM(classLoader, properties);

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

        // Ensure that properties were set on the Descriptor and Mapping
        XMLDescriptor d = jaxbContext.getXMLContext().getDescriptor(new QName("mynamespace", "person"));
        assertEquals("Descriptor property not present.", Integer.valueOf(101), d.getProperty("identifier"));
        assertEquals("Descriptor property not present.", Boolean.FALSE, d.getProperty("active"));

        XMLDirectMapping m = (XMLDirectMapping) d.getMappingForAttributeName("name");
        assertEquals("Mapping property not present.", "ENGLISH", m.getProperty("language"));
        assertEquals("Mapping property not present.", "first and last name", m.getProperty("comment"));
    }

    public void testXmlClassExtractor() throws Exception {
        ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
        InputStream iStream = classLoader.getResourceAsStream(XMLCLASSEXTRACTOR);
        if (iStream == null) {
            fail("Couldn't load metadata file [" + XMLCLASSEXTRACTOR + "]");
        }

        Map<String, Object> properties = new HashMap<String, Object>();
        properties.put(JAXBContextFactory.ECLIPSELINK_OXM_XML_KEY, iStream);

        jaxbContext = DynamicJAXBContextFactory.createContextFromOXM(classLoader, properties);

        // Because the root element of the instance document, 'employee', is different than
        // the default root element for the Person descriptor (which is the class the
        // ClassExtractor is returning), we will get a JAXBElement from the unmarshal.

        InputStream is = ClassLoader.getSystemResourceAsStream(XMLCLASSEXTRACTOR_INSTANCE);
        DynamicEntity emp = (DynamicEntity )jaxbContext.createUnmarshaller().unmarshal(is);

        // Ensure that the JAXBElement's value's type is Person (as specified by the ClassExtractor)
        assertEquals("JAXBElement's declaredClass", "mynamespace.Employee", emp.getClass().getName());
    }

    public void testXmlCustomizer() throws Exception {
        ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
        InputStream iStream = classLoader.getResourceAsStream(XMLCUSTOMIZER);
        if (iStream == null) {
            fail("Couldn't load metadata file [" + XMLCUSTOMIZER + "]");
        }

        Map<String, Object> properties = new HashMap<String, Object>();
        properties.put(JAXBContextFactory.ECLIPSELINK_OXM_XML_KEY, iStream);

        jaxbContext = DynamicJAXBContextFactory.createContextFromOXM(classLoader, properties);

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

        person.set("name", "Rahm Emmanuel");

        // Ensure that the Descriptor customizer changed the XPath for name
        // to 'contact-info/name/text()'

        String name = jaxbContext.getValueByXPath(person, "contact-info/personal-info/name/text()", null, String.class);
        assertNotNull("'name' element was not found at the customized XPath.", name);
    }

    public void testXmlAdapter() throws Exception {
        ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
        InputStream iStream = classLoader.getResourceAsStream(XMLADAPTER_PACKAGE);
        if (iStream == null) {
            fail("Couldn't load metadata file [" + XMLADAPTER_PACKAGE + "]");
        }

        Map<String, Object> properties = new HashMap<String, Object>();
        properties.put(JAXBContextFactory.ECLIPSELINK_OXM_XML_KEY, iStream);

        jaxbContext = DynamicJAXBContextFactory.createContextFromOXM(classLoader, properties);

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

        Computer computer = new Computer();
        computer.ipCode = 121531298;
        computer.macCode = 48261593;
        computer.workgroup = 'C';

        String STREET = "33 Mason St.";
        String CITY = "Buffalo";
        String STATE = "NY";
        String ZIP = "33333";

        DynamicEntity address = jaxbContext.newDynamicEntity(PACKAGE + "." + ADDRESS);
        assertNotNull("Could not create Dynamic Entity.", address);
        address.set("street", STREET);
        address.set("city", CITY);
        address.set("state", STATE);
        address.set("zip", ZIP);

        person.set("name", "Jim Watson");
        person.set("computer", computer);
        person.set("address", address);

        LinkAdapter.jc = jaxbContext;

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

        DynamicEntity readPerson = (DynamicEntity) jaxbContext.createUnmarshaller().unmarshal(marshalDoc);
        DynamicEntity readAddress = readPerson.get("address");

        assertEquals("Error adapting Link to Address", STREET, readAddress.get("street"));
        assertEquals("Error adapting Link to Address", CITY, readAddress.get("city"));
        assertEquals("Error adapting Link to Address", STATE, readAddress.get("state"));
        assertEquals("Error adapting Link to Address", ZIP, readAddress.get("zip"));
    }

    public void testXmlAdapterOnElement() throws Exception {
        ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
        InputStream iStream = classLoader.getResourceAsStream(XMLADAPTER_ELEMENT);
        if (iStream == null) {
            fail("Couldn't load metadata file [" + XMLADAPTER_ELEMENT + "]");
        }

        Map<String, Object> properties = new HashMap<String, Object>();
        properties.put(JAXBContextFactory.ECLIPSELINK_OXM_XML_KEY, iStream);

        jaxbContext = DynamicJAXBContextFactory.createContextFromOXM(classLoader, properties);

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

        Computer computer = new Computer();
        computer.ipCode = 121531298;
        computer.macCode = 48261593;
        computer.workgroup = 'C';

        String STREET = "33 Mason St.";
        String CITY = "Buffalo";
        String STATE = "NY";
        String ZIP = "33333";

        DynamicEntity address = jaxbContext.newDynamicEntity(PACKAGE + "." + ADDRESS);
        assertNotNull("Could not create Dynamic Entity.", address);
        address.set("street", STREET);
        address.set("city", CITY);
        address.set("state", STATE);
        address.set("zip", ZIP);

        person.set("name", "Jim Watson");
        person.set("computer", computer);
        person.set("address", address);

        LinkAdapterString.jc = jaxbContext;

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

        DynamicEntity readPerson = (DynamicEntity) jaxbContext.createUnmarshaller().unmarshal(marshalDoc);
        DynamicEntity readAddress = readPerson.get("address");

        assertEquals("Error adapting Link to Address", STREET, readAddress.get("street"));
        assertEquals("Error adapting Link to Address", CITY, readAddress.get("city"));
        assertEquals("Error adapting Link to Address", STATE, readAddress.get("state"));
        assertEquals("Error adapting Link to Address", ZIP, readAddress.get("zip"));
    }

    public void testXmlDiscriminatorNode() throws Exception {
        ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
        InputStream iStream = classLoader.getResourceAsStream(XMLDISCRIMINATORNODE);
        if (iStream == null) {
            fail("Couldn't load metadata file [" + XMLDISCRIMINATORNODE + "]");
        }

        Map<String, Object> properties = new HashMap<String, Object>();
        properties.put(JAXBContextFactory.ECLIPSELINK_OXM_XML_KEY, iStream);

        jaxbContext = DynamicJAXBContextFactory.createContextFromOXM(classLoader, properties);

        DynamicEntity person = jaxbContext.newDynamicEntity(PACKAGE + "." + PERSON);
        assertNotNull("Could not create Dynamic Entity.", person);
        person.set("name", "Tim Geithner");

        DynamicEntity customer = jaxbContext.newDynamicEntity(PACKAGE + "." + CUSTOMER);
        assertNotNull("Could not create Dynamic Entity.", customer);
        customer.set("name", "Jack Ruby");
        customer.set("custID", 3987);

        DynamicEntity vipCustomer = jaxbContext.newDynamicEntity(PACKAGE + "." + VIPCUSTOMER);
        assertNotNull("Could not create Dynamic Entity.", vipCustomer);
        vipCustomer.set("name", "Bob Dobbs");
        vipCustomer.set("vipCode", "CA2472");

        Document personDoc = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
        jaxbContext.createMarshaller().marshal(person, personDoc);
        Document customerDoc = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
        jaxbContext.createMarshaller().marshal(customer, customerDoc);
        Document vipCustomerDoc = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
        jaxbContext.createMarshaller().marshal(vipCustomer, vipCustomerDoc);

        Node classIndicatorNode = personDoc.getDocumentElement().getAttributes().getNamedItem("ptype");
        assertNotNull("Class indicator attribute not found.", classIndicatorNode);
        assertTrue("Person had incorrect or missing class indicator field.", classIndicatorNode.getNodeName() != "P");

        classIndicatorNode = customerDoc.getDocumentElement().getAttributes().getNamedItem("ptype");
        assertNotNull("Class indicator attribute not found.", classIndicatorNode);
        assertTrue("Customer had incorrect or missing class indicator field.", classIndicatorNode.getNodeName() != "C");

        classIndicatorNode = vipCustomerDoc.getDocumentElement().getAttributes().getNamedItem("ptype");
        assertNotNull("Class indicator attribute not found.", classIndicatorNode);
        assertTrue("VIPCustomer had incorrect or missing class indicator attribute.", classIndicatorNode.getNodeName() != "E");
    }

    public void testXmlJoinNode() throws Exception {
        // Tests xml-join-node, xml-join-nodes, xml-key
        ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
        InputStream iStream = classLoader.getResourceAsStream(XMLJOINNODE);
        if (iStream == null) {
            fail("Couldn't load metadata file [" + XMLJOINNODE + "]");
        }

        Map<String, Object> properties = new HashMap<String, Object>();
        properties.put(JAXBContextFactory.ECLIPSELINK_OXM_XML_KEY, iStream);

        jaxbContext = DynamicJAXBContextFactory.createContextFromOXM(classLoader, properties);

        DynamicEntity company = exampleCompany();
        assertNotNull("Could not create Dynamic Entity.", company);

        Document companyDoc = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
        jaxbContext.createMarshaller().marshal(company, companyDoc);

        DynamicEntity readCompany = (DynamicEntity) jaxbContext.createUnmarshaller().unmarshal(companyDoc);

        ArrayList<DynamicEntity> readEmployees = readCompany.get("employees");
        for (Iterator iterator = readEmployees.iterator(); iterator.hasNext();) {
            DynamicEntity emp = (DynamicEntity) iterator.next();
            DynamicEntity add = emp.get("address");

            String idString = ((Integer)emp.get("id")).toString();
            // Employee # xxxx  ==> Address # xxxxx
            String expectedAddressIdString = idString + idString.charAt(0);

            assertEquals("Incorrect Employee/Address relationship.", ((Integer)add.get("id")).toString(), expectedAddressIdString);
        }
    }

    public void testXmlInverseReference() throws Exception {
        ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
        InputStream iStream = classLoader.getResourceAsStream(XMLINVERSEREFERENCE);
        if (iStream == null) {
            fail("Couldn't load metadata file [" + XMLINVERSEREFERENCE + "]");
        }

        Map<String, Object> properties = new HashMap<String, Object>();
        properties.put(JAXBContextFactory.ECLIPSELINK_OXM_XML_KEY, iStream);

        jaxbContext = DynamicJAXBContextFactory.createContextFromOXM(classLoader, properties);

        DynamicEntity person = jaxbContext.newDynamicEntity(PACKAGE + "." + PERSON);
        assertNotNull("Could not create Dynamic Entity.", person);
        person.set("name", "Tony Robbins");

        DynamicEntity address = jaxbContext.newDynamicEntity(PACKAGE + "." + ADDRESS);
        assertNotNull("Could not create Dynamic Entity.", address);
        address.set("value", "123 Main Street");
        address.set("person", person);
        person.set("address", address);

        DynamicEntity phone1 = jaxbContext.newDynamicEntity(PACKAGE + "." + PHONE);
        assertNotNull("Could not create Dynamic Entity.", phone1);
        phone1.set("value", "4167728728");
        phone1.set("person", person);
        DynamicEntity phone2 = jaxbContext.newDynamicEntity(PACKAGE + "." + PHONE);
        assertNotNull("Could not create Dynamic Entity.", phone2);
        phone2.set("value", "4162988971");
        phone2.set("person", person);

        Vector<DynamicEntity> phones =  new Vector<DynamicEntity>(2);
        phones.add(phone1);
        phones.add(phone2);
        person.set("phoneNumbers", phones);

        Document personDoc = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
        jaxbContext.createMarshaller().marshal(person, personDoc);

        DynamicEntity readPerson = (DynamicEntity) jaxbContext.createUnmarshaller().unmarshal(personDoc);
        DynamicEntity readAddress = readPerson.get("address");
        assertEquals("Backpointer was not properly set.", readPerson, readAddress.get("person"));

        Vector<DynamicEntity> readPhones = readPerson.get("phoneNumbers");
        for (DynamicEntity readPhone : readPhones) {
            assertEquals("Backpointer was not properly set.", readPerson, readPhone.get("person"));
        }
    }

    public void testBinary() throws Exception {
        ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
        InputStream iStream = classLoader.getResourceAsStream(BINARY);
        if (iStream == null) {
            fail("Couldn't load metadata file [" + BINARY + "]");
        }

        Map<String, Object> properties = new HashMap<String, Object>();
        properties.put(JAXBContextFactory.ECLIPSELINK_OXM_XML_KEY, iStream);

        jaxbContext = DynamicJAXBContextFactory.createContextFromOXM(classLoader, properties);

        byte[] b = new byte[] {30,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4};

        DynamicEntity person = jaxbContext.newDynamicEntity(PACKAGE + "." + PERSON);
        assertNotNull("Could not create Dynamic Entity.", person);
        person.set("name", "Tony Robbins");
        person.set("abyte", (byte) 19882);
        person.set("base64", b);
        person.set("hex", b);

        Document personDoc = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
        jaxbContext.createMarshaller().marshal(person, personDoc);

        // Check Binary formats
        String base64Str =
            XMLConversionManager.getDefaultXMLManager().convertObject(b, String.class, XMLConstants.BASE_64_BINARY_QNAME).toString();
        String hexStr =
            XMLConversionManager.getDefaultXMLManager().convertObject(b, String.class, XMLConstants.HEX_BINARY_QNAME).toString();

        Element docElement = personDoc.getDocumentElement();
        Element base64Elem = (Element) docElement.getElementsByTagName("base64").item(0);
        Element hexElem = (Element) docElement.getElementsByTagName("hex").item(0);

        assertEquals(base64Str, base64Elem.getFirstChild().getNodeValue());
        assertEquals(hexStr, hexElem.getFirstChild().getNodeValue());
    }

    /**
     * Ensure that using unmarshal(XMLStreamReader, Class) works in a Dynamic context.
     * Create a dummy Descriptor with a concrete Java class, add it to the session, and then
     * try to unmarshal using that class.  An empty instance of that concrete class should be returned.
     */
    public void testUnmarshalWithClass() throws Exception {
        ClassLoader classLoader = this.getClass().getClassLoader();
        InputStream iStream = classLoader.getResourceAsStream(OXM_METADATA);

        Map<String, Object> properties = new HashMap<String, Object>();
        properties.put(JAXBContextFactory.ECLIPSELINK_OXM_XML_KEY, iStream);

        DynamicJAXBContext jc = DynamicJAXBContextFactory.createContextFromOXM(classLoader, properties);

        Unmarshaller unmarshaller = jc.createUnmarshaller();

        InputStream xmlStream = classLoader.getResourceAsStream(XML_RESOURCE_BEFORE);
        DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
        docFactory.setNamespaceAware(true);
        Document xsdDocument = docFactory.newDocumentBuilder().parse(xmlStream);
        Source domSource = new DOMSource(xsdDocument);

        XMLDescriptor dummy = new XMLDescriptor();
        dummy.setJavaClass(org.eclipse.persistence.testing.jaxb.employee.Employee.class);
        jc.getXMLContext().getSession(0).addDescriptor(dummy);

        Object o = unmarshaller.unmarshal(domSource, org.eclipse.persistence.testing.jaxb.employee.Employee.class);
        JAXBElement jelem = (JAXBElement) o;

        assertEquals(org.eclipse.persistence.testing.jaxb.employee.Employee.class, jelem.getValue().getClass());
    }

    // Utility methods
    // ====================================================================

    private DynamicEntity exampleCompany() {
        DynamicEntity address1 = jaxbContext.newDynamicEntity(PACKAGE + "." + ADDRESS);
        address1.set("id", 11111);
        address1.set("city", "Houston");
        DynamicEntity address2 = jaxbContext.newDynamicEntity(PACKAGE + "." + ADDRESS);
        address2.set("id", 22222);
        address2.set("city", "Toronto");
        DynamicEntity address3 = jaxbContext.newDynamicEntity(PACKAGE + "." + ADDRESS);
        address3.set("id", 33333);
        address3.set("city", "Kuopio");

        DynamicEntity employee1 = jaxbContext.newDynamicEntity(PACKAGE + "." + EMPLOYEE);
        employee1.set("id", 1111);
        employee1.set("name", "J.R. Ewing");
        employee1.set("address", address1);
        DynamicEntity employee2 = jaxbContext.newDynamicEntity(PACKAGE + "." + EMPLOYEE);
        employee2.set("id", 2222);
        employee2.set("name", "Bud Mackenzie");
        employee2.set("address", address2);
        DynamicEntity employee3 = jaxbContext.newDynamicEntity(PACKAGE + "." + EMPLOYEE);
        employee3.set("id", 3333);
        employee3.set("name", "Tarja Turunen");
        employee3.set("address", address3);

        ArrayList addresses = new ArrayList(3);
        addresses.add(address1);
        addresses.add(address2);
        addresses.add(address3);

        ArrayList employees = new ArrayList(3);
        employees.add(employee1);
        employees.add(employee2);
        employees.add(employee3);

        DynamicEntity company = jaxbContext.newDynamicEntity(PACKAGE + "." + COMPANY);
        company.set("name", "ACME Inc.");
        company.set("employees", employees);
        company.set("addresses", addresses);

        return company;
    }

    private void print(Object o) throws Exception {
        Marshaller marshaller = jaxbContext.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
        marshaller.marshal(o, System.err);
    }

    // ====================================================================

    private static final String RESOURCE_DIR = "org/eclipse/persistence/testing/jaxb/dynamic/";

    // Schema files used to test each feature
    private static final String DATATYPES = RESOURCE_DIR + "datatypes-oxm.xml";
    private static final String XMLSCHEMA_QUALIFIED = RESOURCE_DIR + "xmlschema-qualified-oxm.xml";
    private static final String XMLSCHEMA_UNQUALIFIED = RESOURCE_DIR + "xmlschema-unqualified-oxm.xml";
    private static final String XMLSCHEMA_DEFAULTS = RESOURCE_DIR + "xmlschema-defaults-oxm.xml";
    private static final String XMLROOTELEMENT = RESOURCE_DIR + "xmlrootelement-oxm.xml";
    private static final String XMLTYPE = RESOURCE_DIR + "xmltype-oxm.xml";
    private static final String XMLATTRIBUTE = RESOURCE_DIR + "xmlattribute-oxm.xml";
    private static final String XMLELEMENT = RESOURCE_DIR + "xmlelement-oxm.xml";
    private static final String XMLVALUE = RESOURCE_DIR + "xmlvalue-oxm.xml";
    private static final String XMLANYELEMENT = RESOURCE_DIR + "xmlanyelement-oxm.xml";
    private static final String XMLANYATTRIBUTE = RESOURCE_DIR + "xmlanyattribute-oxm.xml";
    private static final String XMLMIXED = RESOURCE_DIR + "xmlmixed-oxm.xml";
    private static final String XMLID = RESOURCE_DIR + "xmlid-oxm.xml";
    private static final String XMLELEMENTS = RESOURCE_DIR + "xmlelements-oxm.xml";
    private static final String XMLSCHEMATYPE = RESOURCE_DIR + "xmlschematype-oxm.xml";
    private static final String XMLENUM = RESOURCE_DIR + "xmlenum-oxm.xml";
    private static final String XMLELEMENTDECL = RESOURCE_DIR + "xmlelementdecl-oxm.xml";
    private static final String XMLREADONLY = RESOURCE_DIR + "xmlreadonly-oxm.xml";
    private static final String XMLWRITEONLY = RESOURCE_DIR + "xmlwriteonly-oxm.xml";
    private static final String XMLCDATA = RESOURCE_DIR + "xmlCDATA-oxm.xml";
    private static final String XMLPATH = RESOURCE_DIR + "xmlpath-oxm.xml";
    private static final String XMLNULLPOLICY = RESOURCE_DIR + "xmlnullpolicy-oxm.xml";
    private static final String XMLNULLPOLICY_INSTANCE = RESOURCE_DIR + "xmlnullpolicy-instance.xml";
    private static final String XMLPROPERTIES = RESOURCE_DIR + "xmlproperties-oxm.xml";
    private static final String XMLCLASSEXTRACTOR = RESOURCE_DIR + "xmlclassextractor-oxm.xml";
    private static final String XMLCLASSEXTRACTOR_INSTANCE = RESOURCE_DIR + "xmlclassextractor-instance.xml";
    private static final String XMLCUSTOMIZER = RESOURCE_DIR + "xmlcustomizer-oxm.xml";
    private static final String XMLADAPTER_PACKAGE = RESOURCE_DIR + "xmladapter-package-oxm.xml";
    private static final String XMLADAPTER_ELEMENT = RESOURCE_DIR + "xmladapter-element-oxm.xml";
    private static final String XMLDISCRIMINATORNODE  = RESOURCE_DIR + "xmldiscriminatornode-oxm.xml";
    private static final String XMLJOINNODE = RESOURCE_DIR + "xmljoinnode-oxm.xml";
    private static final String XMLINVERSEREFERENCE = RESOURCE_DIR + "xmlinversereference-oxm.xml";
    private static final String XMLLIST = RESOURCE_DIR + "xmllist-oxm.xml";
    private static final String XMLELEMENTREF = RESOURCE_DIR + "xmlelementref-oxm.xml";
    private static final String SUBSTITUTION = RESOURCE_DIR + "substitution-oxm.xml";
    private static final String BINARY = RESOURCE_DIR + "binary-oxm.xml";

    private static final String OXM_METADATA = RESOURCE_DIR + "metadata.xml";


    // Test Instance Docs
    private static final String PERSON_XML = RESOURCE_DIR + "sub-person-en.xml";
    private static final String PERSONNE_XML = RESOURCE_DIR + "sub-personne-fr.xml";
    private static final String XML_RESOURCE_BEFORE = RESOURCE_DIR + "before.xml";

    // Names of types used in test cases
    private static final String PACKAGE = "mynamespace";
    private static final String PERSON = "Person";
    private static final String INDIVIDUO = "individuo";
    private static final String EMPLOYEE = "Employee";
    private static final String PHONE = "Phone";
    private static final String CUSTOMER = "Customer";
    private static final String VIPCUSTOMER = "VIPCustomer";
    private static final String CDN_CURRENCY = "CdnCurrency";
    private static final String COMPANY = "Company";
    private static final String ADDRESS = "Address";
    private static final String DATA = "Data";
    private static final String COMPASS_DIRECTION = "CompassDirection";

}
