diff --git a/jaxb-ri/runtime/impl/pom.xml b/jaxb-ri/runtime/impl/pom.xml index 6b7154dd8..024cb9562 100644 --- a/jaxb-ri/runtime/impl/pom.xml +++ b/jaxb-ri/runtime/impl/pom.xml @@ -89,6 +89,7 @@ --add-opens org.glassfish.jaxb.runtime/com.sun.xml.bind.v2=java.xml.bind --add-opens org.glassfish.jaxb.runtime/com.sun.xml.bind.v2.schemagen=java.xml.bind + --add-opens org.glassfish.jaxb.runtime/com.sun.xml.bind.v2.schemagen.xmlidref=java.xml.bind diff --git a/jaxb-ri/runtime/impl/src/test/java/com/sun/xml/bind/v2/schemagen/MarshallingAbstractTest.java b/jaxb-ri/runtime/impl/src/test/java/com/sun/xml/bind/v2/schemagen/MarshallingAbstractTest.java new file mode 100644 index 000000000..1147804c1 --- /dev/null +++ b/jaxb-ri/runtime/impl/src/test/java/com/sun/xml/bind/v2/schemagen/MarshallingAbstractTest.java @@ -0,0 +1,271 @@ +/* + * Copyright (c) 1997, 2019 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Distribution License v. 1.0, which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +package com.sun.xml.bind.v2.schemagen; + +import org.junit.Assert; +import org.junit.Test; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlElementWrapper; +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlSeeAlso; +import javax.xml.bind.annotation.XmlType; +import javax.xml.bind.annotation.XmlValue; +import javax.xml.XMLConstants; +import javax.xml.bind.JAXBContext; +import javax.xml.bind.JAXBElement; +import javax.xml.bind.Marshaller; +import javax.xml.bind.Unmarshaller; +import javax.xml.transform.stream.StreamSource; +import javax.xml.validation.Schema; +import javax.xml.validation.SchemaFactory; + +import com.sun.xml.bind.v2.schemagen.xmlidref.JaxbConcreteContainer; +import com.sun.xml.bind.v2.schemagen.xmlidref.JaxbConcreteDeployment; +import com.sun.xml.bind.v2.schemagen.xmlidref.JaxbContainer; +import com.sun.xml.bind.v2.schemagen.xmlidref.JaxbDistribution; +import com.sun.xml.bind.v2.schemagen.xmlidref.JaxbEnvironmentModel; + +import java.io.StringReader; +import java.io.StringWriter; +import java.util.ArrayList; +import java.util.Collection; + +import junit.framework.TestCase; +import junit.textui.TestRunner; + +public class MarshallingAbstractTest extends TestCase { + public static void main(String[] args) { + TestRunner.run(MarshallingAbstractTest.class); + } + + @XmlSeeAlso({B.class, C.class}) + abstract static class A { + //marshal/unmarshal of list elements containing elements of type = A will work without @XmlValue annotation... + @XmlValue + protected String value; + } + + @XmlAccessorType(XmlAccessType.FIELD) + @XmlType(name = "ClassType1") + public static class B extends A { + public B() {} + public B(String value) { + this.value = value; + } + } + + @XmlAccessorType(XmlAccessType.FIELD) + @XmlType(name = "ClassType2") + public static class C extends A { + public C() {} + public C(String value) { + this.value = value; + } + } + + @XmlRootElement(name="root") + @XmlAccessorType(XmlAccessType.FIELD) + static class Mapping { + @XmlElementWrapper(name = "list") + @XmlElement(name="element") + Collection list = new ArrayList(); + A element1; + A element2; + } + + @Test + public void testMarshalSingleElement() throws Exception { + JAXBContext jc = JAXBContext.newInstance(Mapping.class); + Marshaller marshaller = jc.createMarshaller(); + marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); + StringWriter resultWriter = new StringWriter(); + Mapping mapping = new Mapping(); + mapping.element1 = new B("B1"); + mapping.element2 = new C("C1"); + marshaller.marshal(mapping, resultWriter); + + String expectedXml1 = "\n\n" + + " \n" + + " B1\n" + + " C1\n" + + "\n"; + Assert.assertEquals(resultWriter.toString(), expectedXml1); + } + + @Test + public void testMarshalCollection() throws Exception { + JAXBContext jc = JAXBContext.newInstance(Mapping.class); + Marshaller marshaller = jc.createMarshaller(); + marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); + StringWriter resultWriter = new StringWriter(); + Mapping mapping = new Mapping(); + mapping.element1 = new B("B1"); + mapping.element2 = new C("C1"); + mapping.list.add(new B("B")); + mapping.list.add(new C("C")); + String expectedXml2 = "\n\n" + + " \n" + + " B\n" + + " C\n" + + " \n" + + " B1\n" + + " C1\n" + + "\n"; + marshaller.marshal(mapping, resultWriter); + Assert.assertEquals(resultWriter.toString(), expectedXml2); + } + + @Test + public void testUnmarshalSingleElement() throws Exception { + JAXBContext jc = JAXBContext.newInstance(Mapping.class); + Unmarshaller unmarshaller = jc.createUnmarshaller(); + //works without list.. + String sourceXml1 = "\n\n" + + " B1\n" + + " C1\n" + + "\n"; + JAXBElement element = unmarshaller.unmarshal(new StreamSource(new StringReader(sourceXml1)), Mapping.class); + Assert.assertNotNull(element.getValue()); + Assert.assertEquals(B.class, element.getValue().element1.getClass()); + Assert.assertEquals(C.class, element.getValue().element2.getClass()); + } + + @Test + public void testUnmarshalCollection() throws Exception { + JAXBContext jc = JAXBContext.newInstance(Mapping.class); + Unmarshaller unmarshaller = jc.createUnmarshaller(); + //don't work -> try to instantiate the abstract class + String sourceXml2 = "\n\n" + + " \n" + + " B\n" + + " C\n" + + " \n" + + " B1\n" + + " C1\n" + + "\n"; + + try { + JAXBElement element = unmarshaller.unmarshal(new StreamSource(new StringReader(sourceXml2)), Mapping.class); + Assert.assertEquals(2, element.getValue().list.size()); + } + catch (Throwable e) { + Assert.fail(); + } + } + + @Test + public void testXmlIDRefMarshal() throws Exception { + + JAXBContext cont = JAXBContext.newInstance(JaxbEnvironmentModel.class); + JaxbEnvironmentModel envModel = new JaxbEnvironmentModel(); + JaxbDistribution dist = new JaxbDistribution(); + JaxbConcreteDeployment dep = new JaxbConcreteDeployment(); + dep.setContextRoot("Context-Root"); + dist.addDeployment(dep); + envModel.setDistribution(dist); + JaxbContainer container = new JaxbConcreteContainer(); + container.addDeployment(dep); + envModel.setContainer(container); + + String sourceXsd = "\n" + + "\n" + + "\n" + + " \n" + + "\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + "\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + "\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + "\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + "\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + "\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + "\n" + + " \n" + + " \n" + + " \n" + + ""; + SchemaFactory sf = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); + Schema schema = sf.newSchema(new StreamSource(new StringReader(sourceXsd))); + + Marshaller marshal = cont.createMarshaller(); + marshal.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); + marshal.setSchema(schema); + StringWriter resultWriter = new StringWriter(); + marshal.marshal(envModel, resultWriter); + + String expectedXml = "\n" + + "\n" + + " \n" + + " \n" + + " Context-Root\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " Context-Root\n" + + " \n" + + " \n" + + " \n" + + "\n"; + + Assert.assertEquals(resultWriter.toString(), expectedXml); + } + +} \ No newline at end of file diff --git a/jaxb-ri/runtime/impl/src/test/java/com/sun/xml/bind/v2/schemagen/xmlidref/JaxbConcreteContainer.java b/jaxb-ri/runtime/impl/src/test/java/com/sun/xml/bind/v2/schemagen/xmlidref/JaxbConcreteContainer.java new file mode 100644 index 000000000..e04f872c2 --- /dev/null +++ b/jaxb-ri/runtime/impl/src/test/java/com/sun/xml/bind/v2/schemagen/xmlidref/JaxbConcreteContainer.java @@ -0,0 +1,23 @@ +package com.sun.xml.bind.v2.schemagen.xmlidref; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlType; + +/** + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "concreteContainerType") +public class JaxbConcreteContainer extends JaxbContainer { + + public static final String ELEMENT_NAME = "concreteContainer"; + + @Override + public String toString() { + return "JaxbConcreteContainer{" + + "deployments=" + getDeployments() + + '}'; + } + +} + diff --git a/jaxb-ri/runtime/impl/src/test/java/com/sun/xml/bind/v2/schemagen/xmlidref/JaxbConcreteDeployment.java b/jaxb-ri/runtime/impl/src/test/java/com/sun/xml/bind/v2/schemagen/xmlidref/JaxbConcreteDeployment.java new file mode 100644 index 000000000..3f87fb96e --- /dev/null +++ b/jaxb-ri/runtime/impl/src/test/java/com/sun/xml/bind/v2/schemagen/xmlidref/JaxbConcreteDeployment.java @@ -0,0 +1,20 @@ +package com.sun.xml.bind.v2.schemagen.xmlidref; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlType; + +/** + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "concreteDeploymentType") +public class JaxbConcreteDeployment extends JaxbDeployment { + + @Override + public String toString() { + return "JaxbConcreteDeployment{" + + "contextRoot='" + getContextRoot() + '\'' + + '}'; + } +} + diff --git a/jaxb-ri/runtime/impl/src/test/java/com/sun/xml/bind/v2/schemagen/xmlidref/JaxbContainer.java b/jaxb-ri/runtime/impl/src/test/java/com/sun/xml/bind/v2/schemagen/xmlidref/JaxbContainer.java new file mode 100644 index 000000000..b994ce62c --- /dev/null +++ b/jaxb-ri/runtime/impl/src/test/java/com/sun/xml/bind/v2/schemagen/xmlidref/JaxbContainer.java @@ -0,0 +1,88 @@ +package com.sun.xml.bind.v2.schemagen.xmlidref; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlElementWrapper; +import javax.xml.bind.annotation.XmlIDREF; +import javax.xml.bind.annotation.XmlSeeAlso; +import javax.xml.bind.annotation.XmlType; + +/** + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "containerType", propOrder = { + "deployments" +}) +@XmlSeeAlso({JaxbConcreteContainer.class}) +public abstract class JaxbContainer { + + public static final String ELEMENT_NAME = "container"; + + /** + * Deployments that this container-managed datasource is intended to be used by. + */ + @XmlIDREF + @XmlElementWrapper(name = "deployments", required = true) + @XmlElement(name = JaxbDeployment.ELEMENT_NAME) + private List deployments; + + /** + * Creates new instance of JaxbContainer with empty version, intended for JAXB purposes only! + */ + protected JaxbContainer() { + this.deployments = new ArrayList(); + } + + /** + * {@inheritDoc} + */ + public List getDeployments() { + return Collections.unmodifiableList(this.deployments); + } + + public void setDeployments(final List deployments) { + this.deployments = deployments; + } + + /** + * Adds given Deployment into the list of deployments which use this datasource. + * + * @param deployment Deployment to be added, must not be null + */ + public void addDeployment(final JaxbDeployment deployment) { + if (deployment == null) { + throw new IllegalArgumentException("Cannot add null Deployment!"); + } + this.deployments.add(deployment); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + JaxbContainer that = (JaxbContainer) o; + + return !(deployments != null ? !deployments.equals(that.deployments) : that.deployments != null); + + } + + @Override + public int hashCode() { + int result = super.hashCode(); + result = 31 * result + (deployments != null ? deployments.hashCode() : 0); + return result; + } + + @Override + public String toString() { + return "JaxbContainer{" + + "deployments=" + deployments + + '}'; + } +} diff --git a/jaxb-ri/runtime/impl/src/test/java/com/sun/xml/bind/v2/schemagen/xmlidref/JaxbDeployment.java b/jaxb-ri/runtime/impl/src/test/java/com/sun/xml/bind/v2/schemagen/xmlidref/JaxbDeployment.java new file mode 100644 index 000000000..8229a85ec --- /dev/null +++ b/jaxb-ri/runtime/impl/src/test/java/com/sun/xml/bind/v2/schemagen/xmlidref/JaxbDeployment.java @@ -0,0 +1,62 @@ +package com.sun.xml.bind.v2.schemagen.xmlidref; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlID; +import javax.xml.bind.annotation.XmlSeeAlso; +import javax.xml.bind.annotation.XmlType; + +/** + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "deploymentType") +@XmlSeeAlso({JaxbConcreteDeployment.class}) +public abstract class JaxbDeployment { + + public static final String ELEMENT_NAME = "deployment"; + + /** + * The context root of this deployment, e.g. 'business-central'. + */ + @XmlID + @XmlElement(required = true) + private String contextRoot; + + /** + * {@inheritDoc} + */ + public String getContextRoot() { + return this.contextRoot; + } + + public void setContextRoot(final String contextRoot) { + this.contextRoot = contextRoot; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + + JaxbDeployment that = (JaxbDeployment) o; + + return contextRoot != null ? contextRoot.equals(that.contextRoot) : that.contextRoot == null; + } + + @Override + public int hashCode() { + return contextRoot != null ? contextRoot.hashCode() : 0; + } + + @Override + public String toString() { + return "JaxbDeployment{" + + "contextRoot='" + contextRoot + '\'' + + '}'; + } +} diff --git a/jaxb-ri/runtime/impl/src/test/java/com/sun/xml/bind/v2/schemagen/xmlidref/JaxbDistribution.java b/jaxb-ri/runtime/impl/src/test/java/com/sun/xml/bind/v2/schemagen/xmlidref/JaxbDistribution.java new file mode 100644 index 000000000..b5e7133ba --- /dev/null +++ b/jaxb-ri/runtime/impl/src/test/java/com/sun/xml/bind/v2/schemagen/xmlidref/JaxbDistribution.java @@ -0,0 +1,88 @@ +package com.sun.xml.bind.v2.schemagen.xmlidref; + +import java.util.ArrayList; +import java.util.List; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlElementWrapper; +import javax.xml.bind.annotation.XmlType; + +/** + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "distributionType", propOrder = { + "deployments" +}) +public class JaxbDistribution { + + public static final String ELEMENT_NAME = "distribution"; + + /** + * The list of product deployments that are part of this distribution package. + */ + @XmlElementWrapper(name = "deployments", required = true) + @XmlElement(name = JaxbDeployment.ELEMENT_NAME) + private List deployments; + + /** + * Creates new instance of this class with default values! + */ + public JaxbDistribution() { + this.deployments = new ArrayList(); + } + + /** + * {@inheritDoc} + */ + public List getDeployments() { + return this.deployments; + } + + public void setDeployments(final List deployments) { + this.deployments = deployments; + } + + /** + * Adds given product deployment into the list of deployments that are part of this distribution. + * + * @param deployment product deployment to be added, must not be null + */ + public void addDeployment(final JaxbDeployment deployment) { + if (deployment == null) { + throw new IllegalArgumentException("Cannot add null deployment!"); + } + this.deployments.add(deployment); + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + + final JaxbDistribution that = (JaxbDistribution) o; + + return deployments != null ? deployments.equals(that.deployments) : that + .deployments == null; + + } + + @Override + public int hashCode() { + int result = deployments.hashCode(); + return result; + } + + @Override + public String toString() { + return "JaxbDistribution{" + + "deployments=" + deployments + + '}'; + } +} + diff --git a/jaxb-ri/runtime/impl/src/test/java/com/sun/xml/bind/v2/schemagen/xmlidref/JaxbEnvironmentModel.java b/jaxb-ri/runtime/impl/src/test/java/com/sun/xml/bind/v2/schemagen/xmlidref/JaxbEnvironmentModel.java new file mode 100644 index 000000000..226f82a28 --- /dev/null +++ b/jaxb-ri/runtime/impl/src/test/java/com/sun/xml/bind/v2/schemagen/xmlidref/JaxbEnvironmentModel.java @@ -0,0 +1,67 @@ +package com.sun.xml.bind.v2.schemagen.xmlidref; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlType; + +/** + */ +@XmlRootElement(name = "environmentModel") +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "environmentModelType", propOrder = { + "container", + "distribution" +}) +public class JaxbEnvironmentModel { + + @XmlElement + private JaxbContainer container; + + @XmlElement + private JaxbDistribution distribution; + + public JaxbContainer getContainer() { + return this.container; + } + + public void setContainer(final JaxbContainer container) { + this.container = container; + } + + public JaxbDistribution getDistribution() { + return this.distribution; + } + + public void setDistribution(final JaxbDistribution distribution) { + this.distribution = distribution; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + JaxbEnvironmentModel that = (JaxbEnvironmentModel) o; + + if (container != null ? !container.equals(that.container) : that.container != null) return false; + return !(distribution != null ? !distribution.equals(that.distribution) : that.distribution != null); + + } + + @Override + public int hashCode() { + int result = (container != null ? container.hashCode() : 0); + result = 31 * result + (distribution != null ? distribution.hashCode() : 0); + return result; + } + + @Override + public String toString() { + return "JaxbEnvironmentModel{" + + "container=" + container + + ", distribution=" + distribution + + '}'; + } +}