Add value types from @XmlJavaAdapter into the JAXBContext

git-svn-id: http://svn.us.apache.org/repos/asf/tuscany@1034819 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
rfeng 2010-11-13 17:42:04 +00:00
parent d97b5d71ed
commit d2413f4a13
2 changed files with 87 additions and 16 deletions

View file

@ -24,6 +24,8 @@ import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.lang.reflect.WildcardType;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
@ -39,6 +41,9 @@ import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlSchema;
import javax.xml.bind.annotation.XmlSeeAlso;
import javax.xml.bind.annotation.XmlType;
import javax.xml.bind.annotation.adapters.XmlAdapter;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapters;
import javax.xml.namespace.QName;
import org.apache.tuscany.sca.common.java.collection.LRUCache;
@ -68,7 +73,7 @@ public final class JAXBContextHelper {
public JAXBContextHelper(ExtensionPointRegistry registry) {
cache = new JAXBContextCache(registry);
}
public static JAXBContextHelper getInstance(ExtensionPointRegistry registry) {
UtilityExtensionPoint utilityExtensionPoint = registry.getExtensionPoint(UtilityExtensionPoint.class);
return utilityExtensionPoint.getUtility(JAXBContextHelper.class);
@ -107,7 +112,7 @@ public final class JAXBContextHelper {
return createJAXBContext(dataType);
}
private static Class<?>[] getSeeAlso(Class<?> interfaze) {
if (interfaze == null) {
return null;
@ -131,7 +136,7 @@ public final class JAXBContextHelper {
public void releaseJAXBUnmarshaller(JAXBContext context, Unmarshaller unmarshaller) {
cache.releaseJAXBUnmarshaller(context, unmarshaller);
}
public Marshaller getMarshaller(JAXBContext context) throws JAXBException {
return cache.getMarshaller(context);
}
@ -139,10 +144,11 @@ public final class JAXBContextHelper {
public void releaseJAXBMarshaller(JAXBContext context, Marshaller marshaller) {
cache.releaseJAXBMarshaller(context, marshaller);
}
@SuppressWarnings("unchecked")
public static Object createJAXBElement(JAXBContext context, DataType dataType, Object value) {
Class<?> type = dataType == null ? value.getClass() : dataType.getPhysical();
type = getValueType(type);
QName name = JAXBDataBinding.ROOT_ELEMENT;
if (context != null) {
Object logical = dataType == null ? null : dataType.getLogical();
@ -183,8 +189,8 @@ public final class JAXBContextHelper {
} else {
if (value instanceof JAXBElement) {
Object returnValue = ((JAXBElement)value).getValue();
if (returnValue == null){
if (returnValue == null) {
// TUSCANY-3530
// something went wrong in the transformation that
// generated the JAXBElement. Have seen this when trying
@ -261,6 +267,8 @@ public final class JAXBContextHelper {
if (JAXBDataBinding.NAME.equals(db) || (db != null && db.startsWith("java:")) || db == null) {
if (!d.getPhysical().isInterface() && !JAXBElement.class.isAssignableFrom(d.getPhysical())) {
classes.add(d.getPhysical());
} else {
classes.addAll(findJAXBClassesByInterface(d.getPhysical()));
}
}
if (d.getPhysical() != d.getGenericType()) {
@ -283,6 +291,8 @@ public final class JAXBContextHelper {
Class<?> cls = (Class<?>)type;
if (!cls.isInterface()) {
classSet.add(cls);
} else {
classSet.addAll(findJAXBClassesByInterface(cls));
}
return;
} else if (type instanceof ParameterizedType) {
@ -310,6 +320,65 @@ public final class JAXBContextHelper {
}
}
/**
* Introspect the @XmlJavaTypeAdapter and @XmlSeeAlso for an interface
* @param cls
* @return
*/
private static Set<Class<?>> findJAXBClassesByInterface(Class<?> cls) {
if (!cls.isInterface()) {
return Collections.emptySet();
}
Set<Class<?>> jaxbClasses = new HashSet<Class<?>>();
Class<?> valueType = getValueType(cls);
if (valueType != null) {
jaxbClasses.add(valueType);
}
Class<?>[] others = getSeeAlso(cls);
if (others != null) {
jaxbClasses.addAll(Arrays.asList(others));
}
Package pkg = cls.getPackage();
if (pkg != null) {
XmlJavaTypeAdapters adapters = pkg.getAnnotation(XmlJavaTypeAdapters.class);
if (adapters != null) {
for (XmlJavaTypeAdapter a : adapters.value()) {
jaxbClasses.add(getValueType(a));
}
}
}
return jaxbClasses;
}
public static Class<?> getValueType(Class<?> cls) {
if (cls == null) {
return null;
}
if (cls.isInterface()) {
XmlJavaTypeAdapter adapter = cls.getAnnotation(XmlJavaTypeAdapter.class);
return getValueType(adapter);
} else {
return cls;
}
}
public static Class<?> getValueType(XmlJavaTypeAdapter adapter) {
if (adapter != null) {
Class<? extends XmlAdapter> adapterClass = adapter.value();
if (adapterClass != null) {
Type superClass = adapterClass.getGenericSuperclass();
while (superClass instanceof ParameterizedType && XmlAdapter.class != ((ParameterizedType)superClass)
.getRawType()) {
superClass = ((Class<?>)((ParameterizedType)superClass).getRawType()).getGenericSuperclass();
}
return (Class<?>)((ParameterizedType)superClass).getActualTypeArguments()[0];
}
}
return null;
}
public JAXBContext createJAXBContext(Interface intf) throws JAXBException {
return createJAXBContext(intf, true);
}
@ -460,8 +529,8 @@ public final class JAXBContextHelper {
/**
* The JAXB RI doesn't implement the decapitalization algorithm in the
* JAXB spec. See Sun bug 6505643 for details. This means that instead
* of calling java.beans.Introspector.decapitalize() as the JAXB spec says,
* Tuscany needs to mimic the incorrect JAXB RI algorithm.
* of calling java.beans.Introspector.decapitalize() as the JAXB spec says,
* Tuscany needs to mimic the incorrect JAXB RI algorithm.
*/
public static String jaxbDecapitalize(String name) {
// find first lower case char in name
@ -475,15 +544,15 @@ public final class JAXBContextHelper {
int decap;
if (name.length() == 0) {
decap = 0; // empty string: nothing to do
decap = 0; // empty string: nothing to do
} else if (lower == 0) {
decap = 0; // first char is lower case: nothing to do
decap = 0; // first char is lower case: nothing to do
} else if (lower == 1) {
decap = 1; // one upper followed by lower: decapitalize 1 char
} else if (lower < name.length()) {
decap = lower - 1; // n uppers followed by at least one lower: decapitalize n-1 chars
decap = 1; // one upper followed by lower: decapitalize 1 char
} else if (lower < name.length()) {
decap = lower - 1; // n uppers followed by at least one lower: decapitalize n-1 chars
} else {
decap = name.length(); // all upper case: decapitalize all chars
decap = name.length(); // all upper case: decapitalize all chars
}
return name.substring(0, decap).toLowerCase() + name.substring(decap);

View file

@ -19,6 +19,8 @@
package org.apache.tuscany.sca.databinding.jaxb;
import static org.apache.tuscany.sca.databinding.jaxb.JAXBContextHelper.getValueType;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
@ -120,9 +122,9 @@ public class JAXBDataBinding extends BaseDataBinding {
Object value;
if (targetDataType != null && targetDataType.getPhysical() != sourceDataType.getPhysical()) {
JAXBContext targetContext = contextHelper.createJAXBContext(targetDataType);
value = targetContext.createUnmarshaller().unmarshal(doc, targetDataType.getPhysical());
value = targetContext.createUnmarshaller().unmarshal(doc, getValueType(targetDataType.getPhysical()));
} else {
value = context.createUnmarshaller().unmarshal(doc, sourceDataType.getPhysical());
value = context.createUnmarshaller().unmarshal(doc, getValueType(sourceDataType.getPhysical()));
}
if (isElement && value instanceof JAXBElement) {