diff --git a/src/main/java/org/docx4j/XmlUtils.java b/src/main/java/org/docx4j/XmlUtils.java index b10ff634b8..5296afe2ea 100644 --- a/src/main/java/org/docx4j/XmlUtils.java +++ b/src/main/java/org/docx4j/XmlUtils.java @@ -965,13 +965,31 @@ public static T deepCopy(T value, JAXBContext jc) { if (value==null) { throw new IllegalArgumentException("Can't clone a null argument"); } + + JAXBElement elem; try { - @SuppressWarnings("unchecked") - Class clazz = (Class) value.getClass(); - JAXBElement contentObject = new JAXBElement(new QName(clazz.getSimpleName()), clazz, value); - JAXBSource source = new JAXBSource(jc, contentObject); - JAXBElement elem = jc.createUnmarshaller().unmarshal(source, clazz); + + if (value instanceof JAXBElement) { + + Object wrapped = ((JAXBElement)value).getValue(); + + @SuppressWarnings("unchecked") + Class clazz = wrapped.getClass(); + JAXBElement contentObject = new JAXBElement(new QName(clazz.getSimpleName()), clazz, wrapped); + JAXBSource source = new JAXBSource(jc, contentObject); + elem = jc.createUnmarshaller().unmarshal(source, clazz); + + } else { + + // Usual case + + @SuppressWarnings("unchecked") + Class clazz = (Class) value.getClass(); + JAXBElement contentObject = new JAXBElement(new QName(clazz.getSimpleName()), clazz, value); + JAXBSource source = new JAXBSource(jc, contentObject); + elem = jc.createUnmarshaller().unmarshal(source, clazz); + } /* * Losing content here? diff --git a/src/test/java/org/docx4j/XmlUtilsDeepCopyTest.java b/src/test/java/org/docx4j/XmlUtilsDeepCopyTest.java new file mode 100644 index 0000000000..8b66b1197a --- /dev/null +++ b/src/test/java/org/docx4j/XmlUtilsDeepCopyTest.java @@ -0,0 +1,63 @@ +package org.docx4j; + +import static org.junit.Assert.*; + +import javax.xml.bind.JAXBElement; + +import junit.framework.Assert; + +import org.docx4j.jaxb.Context; +import org.docx4j.wml.CTBookmark; +import org.docx4j.wml.P; +import org.docx4j.wml.R; +import org.junit.Test; + +public class XmlUtilsDeepCopyTest { + + /** + * Test for https://github.com/plutext/docx4j/issues/212 + * + * With v3.3.0 and 3.3.1, deepCopy of a JAXBElement was broken. + * + * With moxY: + * + * java.lang.IllegalArgumentException: javax.xml.bind.UnmarshalException + * + - with linked exception: + [Exception [EclipseLink-25007] (Eclipse Persistence Services - 2.5.2.v20140319-9ad6abd): org.eclipse.persistence.exceptions.XMLMarshalException + Exception Description: A descriptor for class javax.xml.bind.JAXBElement was not found in the project. + For JAXB, if the JAXBContext was bootstrapped using TypeMappingInfo[] you must call a marshal method that accepts TypeMappingInfo + as an input parameter.] + + * With Sun/Oracle, you got a JAXBElement, but null value + + */ + @Test + public void testIssue212() { + + CTBookmark bookmark = Context.getWmlObjectFactory().createCTBookmark(); + JAXBElement el =Context.getWmlObjectFactory().createBodyBookmarkStart(bookmark); + + Object o = XmlUtils.deepCopy(el); + + //System.out.println(XmlUtils.marshaltoString(o)); + + Assert.assertSame(el.getClass(), o.getClass()); + Assert.assertSame(el.getValue().getClass(), ((JAXBElement)o).getValue().getClass()); + } + + @Test + public void testSimpleP() { + + P p = new P(); + p.getContent().add( new R()); + + Object o = XmlUtils.deepCopy(p); + + Assert.assertSame(p.getClass(), o.getClass()); + Assert.assertSame(p.getContent().get(0).getClass(), ((P)o).getContent().get(0).getClass()); + + + } + +}