Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
JAXB fix for unmarshalling objects
  • Loading branch information
hansonr hansonr
hansonr authored and hansonr committed Nov 9, 2018
commit beedf117ab4c41230d8d600cd6b2e118320e1707
20 changes: 16 additions & 4 deletions sources/net.sf.j2s.java.core/src/swingjs/xml/JSJAXBClass.java
Original file line number Diff line number Diff line change
Expand Up @@ -322,16 +322,29 @@ QName finalizeFieldQName(QName qName, String defaultName, int type) {
return this.qname = qname;
case JSJAXBField.TYPE_XML_TYPE:
return this.qname = qualifiedTypeName = qname;
default:
case JSJAXBField.TYPE_ATTRIBUTE:
case JSJAXBField.TYPE_ELEMENT:
return qname;
}
// not possible
return null;
}

private boolean haveXMLTypeNamespace = true;

/**
* Get the default namespace depending upon type.
*
* RootElement: packageNamespace unless the namespace has been set in the annotation
*
* XMLType: the name from the RootElement
*
* XMLAttribute: empty string (surprise!)
*
* XMLElement: the enclosing class's XMLType, if it exists, or the package namespace
*
* @param type
* @return
*/
private String getDefaultNamespace(int type) {
switch (type) {
case JSJAXBField.TYPE_ROOT_ELEMENT:
Expand All @@ -341,11 +354,10 @@ private String getDefaultNamespace(int type) {
return qname.getNamespaceURI();
case JSJAXBField.TYPE_ATTRIBUTE:
return "";
default:
case JSJAXBField.TYPE_ELEMENT:
return (haveXMLTypeNamespace ? qname.getNamespaceURI() : packageNamespace);
}
// not possible
return null;
}

public JSJAXBClass clone() {
Expand Down
7 changes: 3 additions & 4 deletions sources/net.sf.j2s.java.core/src/swingjs/xml/JSJAXBField.java
Original file line number Diff line number Diff line change
Expand Up @@ -493,10 +493,9 @@ public String toString() {

boolean isSimpleType(String javaClassName) {
return (javaClassName != null ? simplePackages(javaClassName)
: isNil || isAttribute
|| asList || isByteArray
|| isArray || qualifiedWrapName != null
|| simplePackages(this.javaClassName));
: isNil || asList || isByteArray || isArray || qualifiedWrapName != null ? true
: xmlType != null ? false
: isAttribute || simplePackages(this.javaClassName));
}

static boolean simplePackages(String javaClassName) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -355,7 +355,7 @@ private void start(DOMNode node, QName qName, Attributes atts) {
String text = JSSAXParser.getSimpleInnerText(node);
if (doc == null) {
doc = node;
setDocAttributes(text, atts);
setDocAttributes(qName, text, atts);
return;
}
// /**
Expand All @@ -370,7 +370,7 @@ private void start(DOMNode node, QName qName, Attributes atts) {
}
}

private void setDocAttributes(String value, Attributes atts) {
private void setDocAttributes(QName qName, String value, Attributes atts) {
if (jaxbClass.xmlValueField != null) {
jaxbClass.xmlValueField.setCharacters(value);
jaxbClass.xmlValueField.setNode(doc);
Expand All @@ -384,6 +384,9 @@ private void setDocAttributes(String value, Attributes atts) {
if (qname.equals("xmlns") || qname.startsWith("xmlns:") || qname.startsWith("xsi:")) {
continue;
}
// attribute assumes uri of tag if "" -- NO!
// if (uri.length() == 0)
// uri = qName.getNamespaceURI();
QName qn = getQnameForAttribute(uri, localName, qname);
JSJAXBField field = getFieldFromQName(qn);
if (field != null) {
Expand Down Expand Up @@ -433,12 +436,18 @@ static JSJAXBClass newUnmarshalledInstance(Class<?> javaClass, Object javaObject
return jjc.clone();
}

public static String needsUnmarshalling(JSJAXBField field, String javaClassName) {
public String needsUnmarshalling(JSJAXBField field, String javaClassName) {
if (field.isSimpleType(javaClassName))
return null;
boolean isMarshalled = false;
if (javaClassName == null)
javaClassName = field.javaClassName;
if (field.xmlType != null) {
String typeClassName = getXMLTypeClassName(field);
if (typeClassName == null)
return null;
javaClassName = typeClassName;
}
try {
isMarshalled = (knownJavaClasses.containsKey(javaClassName)
? knownJavaClasses.get(javaClassName).booleanValue()
Expand All @@ -452,6 +461,15 @@ public static String needsUnmarshalling(JSJAXBField field, String javaClassName)
return (isMarshalled ? javaClassName : null);
}

private String getXMLTypeClassName(JSJAXBField field) {
if (field.xmlType.indexOf(":") >= 0 && !field.xmlType.startsWith("xs:")) {
QName qname = getQnameForAttribute(null, null, field.xmlType);
field = getFieldFromQName(qname);
return (field == null ? null : field.javaClassName);
}
return null;
}

void prepareForUnmarshalling(String defaultNamespace) {
jaxbClass.setUnmarshallerDefaultNamespace(defaultNamespace);
List<String> seeAlso = jaxbClass.seeAlso;
Expand Down Expand Up @@ -487,11 +505,12 @@ private void bindQName(QName q, JSJAXBField field, boolean isSeeAlso) {
return;
Map<String, JSJAXBField> map = (isSeeAlso ? seeAlsoMap : jaxbClass.unmarshallerFieldMap);
map.put(q.getLocalPart(), field);
String namespace = q.getNamespaceURI();
// if (namespace.length() == 0)
// namespace = jaxbClass.getUnmarshallerDefaultNamespace();
// if (namespace != null)
map.put(namespace + ":" + q.getLocalPart(), field);
String qn = q.getNamespaceURI() + ":" + q.getLocalPart();
map.put(qn, field);
map.put("/lc/" + qn.toLowerCase(), field);
// System.out.println("JSJAXBClass#binding " + namespace + ":" +
// q.getLocalPart() + "->" + field.javaName);
}
Expand All @@ -505,6 +524,10 @@ JSJAXBField getFieldFromQName(QName qName) {
f = seeAlsoMap.get(key);
// if (f == null)
// f = seeAlsoMap.get(qName.getLocalPart());

// desparately doing this because I cannot find the capitalization algorithm in JAXB!
if (f == null)
f = jaxbClass.unmarshallerFieldMap.get("/lc/" + key.toLowerCase());
if (f == null)
System.out.println("JSJAXBUnmarshaller could not associate a field with " + qName);
return f;
Expand All @@ -519,14 +542,6 @@ private void setFieldValue(JSJAXBField field) {
if (field.isNil)
return;

// complex object -- unmarshal directly

String className = needsUnmarshalling(field, null);
if (className != null) {
field.setValue(unmarshalField(field, field.boundNode, className), javaObject);
return;
}

// char data for field
if (field.asList) {
field.setValue(fillArrayData(field, field.boundNode, field.xmlCharacterData.trim().split(" "),
Expand Down Expand Up @@ -560,6 +575,15 @@ private void setFieldValue(JSJAXBField field) {

// qualifiedWrapName is null;

String className = needsUnmarshalling(field, null);
if (className != null) {

// complex object -- unmarshal directly

field.setValue(unmarshalField(field, field.boundNode, className), javaObject);
return;
}

String data = (field.isAttribute ? field.xmlAttributeData : field.xmlCharacterData.trim());
String dataType = (field.xmlType == null ? field.javaClassName : field.xmlType);
field.setValue(convertFromType(field, data, dataType, field.xmlType != null), javaObject);
Expand Down
92 changes: 19 additions & 73 deletions sources/net.sf.j2s.java.core/src/test/Test_JAXB_NONE.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package test;

import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.util.Date;

Expand All @@ -14,6 +16,7 @@
import javax.xml.bind.annotation.XmlRegistry;
import javax.xml.namespace.QName;

import javajs.util.Rdr;
import test.jaxb.Root_NONE;

/**
Expand All @@ -25,96 +28,39 @@
@XmlRegistry
public class Test_JAXB_NONE extends Test_ {

// Java read out:
// getPropertyC is =getproPERtyC:propertyC01
// getAToBe
// getAToBe
// getAToBe
// isB2()
// getB3()
// private!getC
// private!getC
// private!getC
// getPropertyAToBe
// getPropertyAToBe
// getPropertyAToBe
//
// <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
// <ns2:RootNone xmlns:ns2="www.jalview.org" ang="?" pi1A="0" pi2A="0" pi3A="3">
// <propertyC>propertyC0</propertyC>
// <AToBe>getAtoBe</AToBe>
// <b2>true</b2>
// <b3>true</b3>
// <c>getC</c>
// <propertyAToBe>getPropertyAtoB</propertyAToBe>
// <propc>=getproPERtyC:propertyC01</propc>
// <propertyc>=getpropertyc:propertyC0</propertyc>
// </ns2:RootNone>
//
// setAToBe:getAtoBe
// setB2()
// setB3()
// private!setC
// setPropertyAToBe:getPropertyAtoB
// setProPERtyC:=getproPERtyC:propertyC01
// setpropertyc:=getpropertyc:propertyC0
// getPropertyAng[].length is 3
// Test_JAXB_NONE OK

// JavaScript read out:
// getPropertyC is =getproPERtyC:propertyC01
// private!getC
// isB2()
// getB3()
// getAToBe
// getPropertyAToBe
//
// <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
// <ns2:RootNone xmlns="www.jalview.org" xmlns:ns2="www.jalview.org" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xs="http://www.w3.org/2001/XMLSchema" Ang="&#8491;" pi1a="0" pi2a="0" pi3a="3">
// <propertyC>propertyC0</propertyC>
// <c>getC</c>
// <propc>=getproPERtyC:propertyC01</propc>
// <propertyc>=getpropertyc:propertyC0</propertyc>
// <b2>true</b2>
// <b3>true</b3>
// <aToBe>getAtoBe</aToBe>
// <propertyAToBe>=getPropertyAtoB</propertyAToBe>
// </ns2:RootNone>
// private!setC
// setProPERtyC:=getproPERtyC:propertyC01
// setpropertyc:=getpropertyc:propertyC0
// setB2()
// setB3()
// setAToBe:getAtoBe
// setPropertyAToBe:=getPropertyAtoB
// getPropertyAng[].length is 3
// Test_JAXB_NONE OK

@XmlElementDecl(namespace = "www.jalview.org", name = "Root")
public static JAXBElement<Root_NONE> createRootModel(Root_NONE value) {
return new JAXBElement<Root_NONE>(new QName("www.jalview.org", "Root"), Root_NONE.class, null, value);
}

public static void main(String[] args) {
JAXBContext jc;
try {
jc = JAXBContext.newInstance(Root_NONE.class);

Root_NONE root = new Root_NONE("test");
root.setPropertyAng("?");
System.out.println("getPropertyC is " + root.getproPERtyC());
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
ByteArrayOutputStream bos = new ByteArrayOutputStream();
// marshaller.marshal(createRootModel(root), bos);
marshaller.marshal(root, bos);
String s = null;
try {
s = new String(bos.toByteArray(), "UTF-8");
System.out.println(s);
System.out.println(s);

Unmarshaller unmarshaller = jc.createUnmarshaller();

// Class<?> c = Test_JAXB_NONE.class;
// InputStream ris = c.getResourceAsStream("jaxb/Root_NONE.xml");
// s = Rdr.streamToUTF8String(new BufferedInputStream(ris));
//ByteArrayInputStream ris = new ByteArrayInputStream(s.getBytes("UTF-8"));

System.out.println(s);

ByteArrayInputStream is = new ByteArrayInputStream(s.getBytes("UTF-8"));




Root_NONE r = (Root_NONE) unmarshaller.unmarshal(is);
assert(r.getPropertyAng().equals("\u212B"));
assert(r.getPropertyAng().equals("?"));
System.out.println("getPropertyAng[].length is " + r.getPropertyAng().getBytes("utf-8").length);
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
Expand Down
11 changes: 11 additions & 0 deletions sources/net.sf.j2s.java.core/src/test/jaxb/Root_NONE.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<RootNone xmlns="package-namespace" ang="?" pi1A="0" pi2A="0" pi3A="3">
<propertyC>propertyC0</propertyC>
<AToBe>getAtoBe</AToBe>
<b2>true</b2>
<b3>true</b3>
<c>getC</c>
<propertyAToBe>=getPropertyAtoB</propertyAToBe>
<propc>=getproPERtyC:propertyC01</propc>
<propertyc>=getpropertyc:propertyC0</propertyc>
</RootNone>