You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cxf.apache.org by bi...@apache.org on 2009/09/04 02:03:14 UTC
svn commit: r811180 - in
/cxf/trunk/rt/databinding/aegis/src/main/java/org/apache/cxf/aegis/type: ./
java5/
Author: bimargulies
Date: Fri Sep 4 00:03:14 2009
New Revision: 811180
URL: http://svn.apache.org/viewvc?rev=811180&view=rev
Log:
Lots of changes in the 'Class->Type' campaign. Still fails two tests.
Added:
cxf/trunk/rt/databinding/aegis/src/main/java/org/apache/cxf/aegis/type/ParameterizedTypeFactory.java (with props)
cxf/trunk/rt/databinding/aegis/src/main/java/org/apache/cxf/aegis/type/SimpleParameterizedType.java (with props)
Modified:
cxf/trunk/rt/databinding/aegis/src/main/java/org/apache/cxf/aegis/type/AbstractTypeCreator.java
cxf/trunk/rt/databinding/aegis/src/main/java/org/apache/cxf/aegis/type/AegisType.java
cxf/trunk/rt/databinding/aegis/src/main/java/org/apache/cxf/aegis/type/DefaultTypeCreator.java
cxf/trunk/rt/databinding/aegis/src/main/java/org/apache/cxf/aegis/type/TypeClassInfo.java
cxf/trunk/rt/databinding/aegis/src/main/java/org/apache/cxf/aegis/type/TypeCreator.java
cxf/trunk/rt/databinding/aegis/src/main/java/org/apache/cxf/aegis/type/TypeUtil.java
cxf/trunk/rt/databinding/aegis/src/main/java/org/apache/cxf/aegis/type/XMLTypeCreator.java
cxf/trunk/rt/databinding/aegis/src/main/java/org/apache/cxf/aegis/type/java5/Java5TypeCreator.java
Modified: cxf/trunk/rt/databinding/aegis/src/main/java/org/apache/cxf/aegis/type/AbstractTypeCreator.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/databinding/aegis/src/main/java/org/apache/cxf/aegis/type/AbstractTypeCreator.java?rev=811180&r1=811179&r2=811180&view=diff
==============================================================================
--- cxf/trunk/rt/databinding/aegis/src/main/java/org/apache/cxf/aegis/type/AbstractTypeCreator.java (original)
+++ cxf/trunk/rt/databinding/aegis/src/main/java/org/apache/cxf/aegis/type/AbstractTypeCreator.java Fri Sep 4 00:03:14 2009
@@ -21,7 +21,7 @@
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
-import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
import java.util.Collection;
import java.util.Map;
@@ -37,9 +37,6 @@
import org.apache.cxf.common.WSDLConstants;
import org.apache.cxf.common.util.XMLSchemaQNames;
-/**
- * @author Hani Suleiman Date: Jun 14, 2005 Time: 11:59:57 PM
- */
public abstract class AbstractTypeCreator implements TypeCreator {
public static final String HTTP_CXF_APACHE_ORG_ARRAYS = "http://cxf.apache.org/arrays";
@@ -92,33 +89,39 @@
return info;
}
- public TypeClassInfo createBasicClassInfo(Class typeClass) {
+ public TypeClassInfo createBasicClassInfo(Type type) {
TypeClassInfo info = new TypeClassInfo();
- info.setDescription("class '" + typeClass.getName() + '\'');
- info.setTypeClass(typeClass);
+ Class typeClass = TypeUtil.getTypeClass(type, false);
+ if (typeClass != null) {
+ info.setDescription("class '" + typeClass.getName() + "'");
+ } else {
+ info.setDescription("type '" + type + "'");
+ }
+ info.setType(type);
return info;
}
public AegisType createTypeForClass(TypeClassInfo info) {
- Class javaType = info.getTypeClass();
+
+ Class javaClass = TypeUtil.getTypeRelatedClass(info.getType());
AegisType result = null;
boolean newType = true;
if (info.getAegisTypeClass() != null) {
result = createUserType(info);
- } else if (isArray(javaType)) {
+ } else if (isArray(javaClass)) {
result = createArrayType(info);
- } else if (isMap(javaType)) {
+ } else if (isMap(javaClass)) {
result = createMapType(info);
- } else if (isHolder(javaType)) {
+ } else if (isHolder(javaClass)) {
result = createHolderType(info);
- } else if (isCollection(javaType)) {
+ } else if (isCollection(javaClass)) {
result = createCollectionType(info);
- } else if (isEnum(javaType)) {
+ } else if (isEnum(javaClass)) {
result = createEnumType(info);
} else {
- AegisType type = getTypeMapping().getType(javaType);
+ AegisType type = getTypeMapping().getType(info.getType());
if (type == null) {
if (info.getTypeName() != null) {
type = getTypeMapping().getType(info.getTypeName());
@@ -149,15 +152,14 @@
}
protected AegisType createHolderType(TypeClassInfo info) {
- if (info.getGenericType() == null) {
- throw new UnsupportedOperationException("To use holder types "
- + "you must have an XML descriptor declaring the component type.");
- }
- Class heldCls = (Class) info.getGenericType();
- info.setTypeClass(heldCls);
+ Type heldType = TypeUtil.getSingleTypeParameter(info.getType());
+ if (heldType == null) {
+ throw new UnsupportedOperationException("Invalid holder type " + info.getType());
+ }
- return createType(heldCls);
+ info.setType(heldType);
+ return createType(heldType);
}
@@ -175,18 +177,19 @@
// If the @ annotation or XML file didn't specify a schema type,
// but the natural type has a schema type mapping, we use that rather
// than create nonsense.
- if (info.getTypeClass().getPackage().getName().startsWith("java")) {
- name = tm.getTypeQName(info.getTypeClass());
+ Class<?> typeClass = TypeUtil.getTypeRelatedClass(info.getType());
+ if (typeClass.getPackage().getName().startsWith("java")) {
+ name = tm.getTypeQName(typeClass);
}
- // if it's still null, we'll take our lumps, but probably end up wih
+ // if it's still null, we'll take our lumps, but probably end up with
// an invalid schema.
if (name == null) {
- name = createQName(info.getTypeClass());
+ name = createQName(typeClass);
}
}
type.setSchemaType(name);
- type.setTypeClass(info.getTypeClass());
+ type.setTypeClass(info.getType());
type.setTypeMapping(getTypeMapping());
return type;
@@ -202,7 +205,7 @@
protected AegisType createArrayType(TypeClassInfo info) {
ArrayType type = new ArrayType();
type.setTypeMapping(getTypeMapping());
- type.setTypeClass(info.getTypeClass());
+ type.setTypeClass(info.getType());
type.setSchemaType(createCollectionQName(info, type.getComponentType()));
if (info.getMinOccurs() != -1) {
@@ -246,7 +249,7 @@
type.setSchemaType(name);
- type.setTypeClass(info.getTypeClass());
+ type.setTypeClass(info.getType());
if (info.getMinOccurs() != -1) {
type.setMinOccurs(info.getMinOccurs());
@@ -284,7 +287,7 @@
QName schemaType = createMapQName(info, keyType, valueType);
MapType type = new MapType(schemaType, keyType, valueType);
type.setTypeMapping(getTypeMapping());
- type.setTypeClass(info.getTypeClass());
+ type.setTypeClass(info.getType());
return type;
}
@@ -405,19 +408,9 @@
* @param t the reflected type.
* @return the type
*/
- public AegisType createType(java.lang.reflect.Type t) {
+ public AegisType createType(Type t) {
TypeClassInfo info = new TypeClassInfo();
- info.setGenericType(t);
- if (t instanceof ParameterizedType) {
- ParameterizedType pt = (ParameterizedType) t;
- java.lang.reflect.Type rawType = pt.getRawType();
- if (rawType instanceof Class) {
- info.setTypeClass((Class)rawType);
- }
- } else if (t instanceof Class) {
- info.setTypeClass((Class)t);
- }
-
+ info.setType(t);
info.setDescription("reflected type " + t.toString());
return createTypeForClass(info);
Modified: cxf/trunk/rt/databinding/aegis/src/main/java/org/apache/cxf/aegis/type/AegisType.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/databinding/aegis/src/main/java/org/apache/cxf/aegis/type/AegisType.java?rev=811180&r1=811179&r2=811180&view=diff
==============================================================================
--- cxf/trunk/rt/databinding/aegis/src/main/java/org/apache/cxf/aegis/type/AegisType.java (original)
+++ cxf/trunk/rt/databinding/aegis/src/main/java/org/apache/cxf/aegis/type/AegisType.java Fri Sep 4 00:03:14 2009
@@ -100,15 +100,12 @@
}
/**
- * @return Returns the java type as a Class. If the type is not a
- * plain class, return null.
+ * @return Returns the java type as a Class.
+ * For a generic, return the raw type. For something
+ * truly exotic, return null.
*/
public Class getTypeClass() {
- if (typeClass instanceof Class) {
- return (Class)typeClass;
- } else {
- return null;
- }
+ return TypeUtil.getTypeRelatedClass(typeClass);
}
/**
Modified: cxf/trunk/rt/databinding/aegis/src/main/java/org/apache/cxf/aegis/type/DefaultTypeCreator.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/databinding/aegis/src/main/java/org/apache/cxf/aegis/type/DefaultTypeCreator.java?rev=811180&r1=811179&r2=811180&view=diff
==============================================================================
--- cxf/trunk/rt/databinding/aegis/src/main/java/org/apache/cxf/aegis/type/DefaultTypeCreator.java (original)
+++ cxf/trunk/rt/databinding/aegis/src/main/java/org/apache/cxf/aegis/type/DefaultTypeCreator.java Fri Sep 4 00:03:14 2009
@@ -20,6 +20,7 @@
import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
+import java.lang.reflect.ParameterizedType;
import org.apache.cxf.aegis.DatabindingException;
import org.apache.cxf.aegis.type.basic.BeanType;
@@ -39,9 +40,9 @@
info.setDescription("method " + m.getName() + " parameter " + index);
if (index >= 0) {
- info.setTypeClass(m.getParameterTypes()[index]);
+ info.setType(m.getParameterTypes()[index]);
} else {
- info.setTypeClass(m.getReturnType());
+ info.setType(m.getReturnType());
}
return info;
@@ -54,8 +55,8 @@
@Override
public AegisType createCollectionType(TypeClassInfo info) {
- if (info.getGenericType() == null) {
- throw new DatabindingException("Cannot create mapping for " + info.getTypeClass().getName()
+ if (!(info.getType() instanceof ParameterizedType)) {
+ throw new DatabindingException("Cannot create mapping for " + info.getType()
+ ", unspecified component type for " + info.getDescription());
}
@@ -65,8 +66,16 @@
@Override
public AegisType createDefaultType(TypeClassInfo info) {
BeanType type = new BeanType();
- type.setSchemaType(createQName(info.getTypeClass()));
- type.setTypeClass(info.getTypeClass());
+ /*
+ * As of this point, we refuse to do this for generics in general.
+ * This might be revisited ... it might turn out to 'just work'.
+ */
+ Class<?> typeClass = TypeUtil.getTypeClass(info.getType(), false);
+ if (typeClass == null) {
+ throw new DatabindingException("Unable to map generic type " + info.getType());
+ }
+ type.setSchemaType(createQName(typeClass));
+ type.setTypeClass(typeClass);
type.setTypeMapping(getTypeMapping());
BeanTypeInfo typeInfo = type.getTypeInfo();
Added: cxf/trunk/rt/databinding/aegis/src/main/java/org/apache/cxf/aegis/type/ParameterizedTypeFactory.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/databinding/aegis/src/main/java/org/apache/cxf/aegis/type/ParameterizedTypeFactory.java?rev=811180&view=auto
==============================================================================
--- cxf/trunk/rt/databinding/aegis/src/main/java/org/apache/cxf/aegis/type/ParameterizedTypeFactory.java (added)
+++ cxf/trunk/rt/databinding/aegis/src/main/java/org/apache/cxf/aegis/type/ParameterizedTypeFactory.java Fri Sep 4 00:03:14 2009
@@ -0,0 +1,35 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.cxf.aegis.type;
+
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+
+/**
+ * Create ParameterizedType objects for some limited cases.
+ */
+public final class ParameterizedTypeFactory {
+ private ParameterizedTypeFactory() {
+ }
+
+ public static ParameterizedType createParameterizedType(Class<?> rawType, Type[] parameters) {
+ return new SimpleParameterizedType(rawType, parameters);
+ }
+}
Propchange: cxf/trunk/rt/databinding/aegis/src/main/java/org/apache/cxf/aegis/type/ParameterizedTypeFactory.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: cxf/trunk/rt/databinding/aegis/src/main/java/org/apache/cxf/aegis/type/SimpleParameterizedType.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/databinding/aegis/src/main/java/org/apache/cxf/aegis/type/SimpleParameterizedType.java?rev=811180&view=auto
==============================================================================
--- cxf/trunk/rt/databinding/aegis/src/main/java/org/apache/cxf/aegis/type/SimpleParameterizedType.java (added)
+++ cxf/trunk/rt/databinding/aegis/src/main/java/org/apache/cxf/aegis/type/SimpleParameterizedType.java Fri Sep 4 00:03:14 2009
@@ -0,0 +1,90 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.cxf.aegis.type;
+
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.util.Arrays;
+
+/**
+ * When an XML file tells is that it wants a List to be a List<x> or a Map to be
+ * a Map<x, y>, we create one of these. We do not tolerate nesting. If we really
+ * wanted the entire apparatus, asm would be more appropriate. This is good enough
+ * to allow us to probe a hash table hashed on Type objects where List<x> might
+ * be in there.
+ */
+class SimpleParameterizedType implements ParameterizedType {
+ private Class<?> rawType;
+ private Type[] parameters;
+
+ SimpleParameterizedType(Class<?> rawType, Type[] parameters) {
+ this.rawType = rawType;
+ this.parameters = parameters;
+ }
+
+ public Type[] getActualTypeArguments() {
+ return parameters;
+ }
+
+ public Type getOwnerType() {
+ // no nested types.
+ return null;
+ }
+
+ public Type getRawType() {
+ return rawType;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + Arrays.hashCode(parameters);
+ result = prime * result + ((rawType == null) ? 0 : rawType.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+
+ ParameterizedType opt = null;
+ try {
+ opt = (ParameterizedType) obj;
+ } catch (ClassCastException cce) {
+ return false;
+ }
+
+ if (opt.getOwnerType() != null) {
+ return false;
+ }
+
+ if (rawType != opt.getRawType()) {
+ return false;
+ }
+
+ return Arrays.equals(parameters, opt.getActualTypeArguments());
+ }
+}
Propchange: cxf/trunk/rt/databinding/aegis/src/main/java/org/apache/cxf/aegis/type/SimpleParameterizedType.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified: cxf/trunk/rt/databinding/aegis/src/main/java/org/apache/cxf/aegis/type/TypeClassInfo.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/databinding/aegis/src/main/java/org/apache/cxf/aegis/type/TypeClassInfo.java?rev=811180&r1=811179&r2=811180&view=diff
==============================================================================
--- cxf/trunk/rt/databinding/aegis/src/main/java/org/apache/cxf/aegis/type/TypeClassInfo.java (original)
+++ cxf/trunk/rt/databinding/aegis/src/main/java/org/apache/cxf/aegis/type/TypeClassInfo.java Fri Sep 4 00:03:14 2009
@@ -19,16 +19,29 @@
package org.apache.cxf.aegis.type;
+import java.lang.reflect.Type;
+
import javax.xml.namespace.QName;
/**
- * Object to carry information for a aegisTypeClass, such as that from an XML mapping file.
+ * Object to carry information for an Aegis type,
+ * such as that from an XML mapping file.
*
* Note that this class has a misleading name. It is used both for
- * aegisTypeClass information that corresponds to a aegisTypeClass, and also for parameters
- * of methods and elements of beans. When describing a top-level aegisTypeClass,
- * minOccurs and maxOccurs are not meaningful. Nillable is only used for
- * parameters. It might be that the code could be deconfused by
+ * type information that corresponds to a type, and also for parameters
+ * of methods and elements of beans. When describing a top-level type,
+ * minOccurs and maxOccurs are not meaningful. Aegis does not have a
+ * very clear model of a 'type', in the sense of an AegisType object
+ * corresponding to some particular XML Schema type, in isolation
+ * from the mapping system.
+ *
+ * Historically, Aegis talked about Java types as Class. However,
+ * we want to be able to keep track, distinctly, of un-erased
+ * generics. That requires java.lang.reflect.Type.
+ *
+ * Nillable is only used for parameters.
+ *
+ * It might be that the code could be deconfused by
* using the nillable property in here for the non-parameters cases
* that look at minOccurs and maxOccurs.
*
@@ -38,24 +51,27 @@
* of a plain boolean.
*/
public class TypeClassInfo {
- private Class typeClass;
+ // The general reflection Type.
+ private Type type;
private Object[] annotations;
- // Object because it can be either a TypeClassInfo or a
- // java.lang.reflect.Type
- private Object genericType;
- // ditto
- private Object keyType;
- // ditto
- private Object valueType;
+
+ // for collection types we pull out the parameters for convenience.
+ private Type keyType;
+ private Type valueType;
+
+ // Preferred element name.
private QName mappedName;
+ // XML schema name for the type.
private QName typeName;
+
// a Class reference to the aegis aegisTypeClass, if the app has specified it
// via XML or via an annotation.
private Class<? extends AegisType> aegisTypeClass;
+
private String description;
private long minOccurs = -1;
private long maxOccurs = -1;
- // not yet implemented
+ // Flat array.
private boolean flat;
private Boolean nillable;
@@ -79,28 +95,20 @@
this.annotations = annotations;
}
- public Object getGenericType() {
- return genericType;
- }
-
- public void setGenericType(Object genericType) {
- this.genericType = genericType;
- }
-
- public Object getKeyType() {
+ public Type getKeyType() {
return keyType;
}
- public void setKeyType(Object keyType) {
+ public void setKeyType(Type keyType) {
this.keyType = keyType;
}
- public Class getTypeClass() {
- return typeClass;
+ public Type getType() {
+ return type;
}
- public void setTypeClass(Class typeClass) {
- this.typeClass = typeClass;
+ public void setType(Type type) {
+ this.type = type;
}
public QName getTypeName() {
@@ -156,11 +164,11 @@
return "TypeClassInfo " + getDescription();
}
- public Object getValueType() {
+ public Type getValueType() {
return valueType;
}
- public void setValueType(Object valueType) {
+ public void setValueType(Type valueType) {
this.valueType = valueType;
}
Modified: cxf/trunk/rt/databinding/aegis/src/main/java/org/apache/cxf/aegis/type/TypeCreator.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/databinding/aegis/src/main/java/org/apache/cxf/aegis/type/TypeCreator.java?rev=811180&r1=811179&r2=811180&view=diff
==============================================================================
--- cxf/trunk/rt/databinding/aegis/src/main/java/org/apache/cxf/aegis/type/TypeCreator.java (original)
+++ cxf/trunk/rt/databinding/aegis/src/main/java/org/apache/cxf/aegis/type/TypeCreator.java Fri Sep 4 00:03:14 2009
@@ -21,13 +21,10 @@
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
+import java.lang.reflect.Type;
import javax.xml.namespace.QName;
-
-/**
- * @author <a href="mailto:dan@envoisolutions.com">Dan Diephouse</a>
- */
public interface TypeCreator {
/**
* Get the mapped name of a method parameter.
@@ -42,17 +39,16 @@
AegisType createType(PropertyDescriptor pd);
- AegisType createType(java.lang.reflect.Type type);
+ AegisType createType(Type type);
AegisType createType(Field f);
- AegisType createType(Class clazz);
-
TypeCreator getParent();
void setParent(TypeCreator creator);
void setTypeMapping(TypeMapping typeMapping);
+
/** Retrieve the classInfo for a method. Needed to get parameters right.
*
* @param m Method object
@@ -60,12 +56,13 @@
* @return info
*/
TypeClassInfo createClassInfo(Method m, int index);
+
/**
- * Retrieve the class info for a class. Needed to get parameters right.
- * @param itemClass
+ * Create class info for a Type.
+ * @param itemType
* @return info
*/
- TypeClassInfo createBasicClassInfo(Class<?> itemClass);
+ TypeClassInfo createBasicClassInfo(Type itemType);
/**
* Turn a TypeClassInfo into a type.
Modified: cxf/trunk/rt/databinding/aegis/src/main/java/org/apache/cxf/aegis/type/TypeUtil.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/databinding/aegis/src/main/java/org/apache/cxf/aegis/type/TypeUtil.java?rev=811180&r1=811179&r2=811180&view=diff
==============================================================================
--- cxf/trunk/rt/databinding/aegis/src/main/java/org/apache/cxf/aegis/type/TypeUtil.java (original)
+++ cxf/trunk/rt/databinding/aegis/src/main/java/org/apache/cxf/aegis/type/TypeUtil.java Fri Sep 4 00:03:14 2009
@@ -18,6 +18,8 @@
*/
package org.apache.cxf.aegis.type;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
import java.util.logging.Logger;
import javax.xml.namespace.QName;
@@ -178,9 +180,64 @@
}
-
public static void setAttributeAttributes(QName name, AegisType type, XmlSchema root) {
String ns = type.getSchemaType().getNamespaceURI();
XmlSchemaUtils.addImportIfNeeded(root, ns);
}
+
+ /**
+ * Utility function to cast a Type to a Class. This throws an unchecked exception if the Type is
+ * not a Class. The idea here is that these Type references should have been checked for
+ * reasonableness before the point of calls to this function.
+ * @param type Reflection type.
+ * @param throwForNonClass whether to throw (true) or return null (false) if the Type
+ * is not a class.
+ * @return the Class
+ */
+ public static Class<?> getTypeClass(Type type, boolean throwForNonClass) {
+ if (type instanceof Class) {
+ return (Class) type;
+ } else if (throwForNonClass) {
+ throw new RuntimeException("Attempt to derive Class from reflection Type " + type);
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Insist that a Type is a parameterized type of one parameter.
+ * This is used to decompose Holders, for example.
+ * @param type the type
+ * @return the parameter, or null if the type is not what we want.
+ */
+ public static Type getSingleTypeParameter(Type type) {
+ if (type instanceof ParameterizedType) {
+ ParameterizedType pType = (ParameterizedType) type;
+ Type[] params = pType.getActualTypeArguments();
+ if (params.length == 1) {
+ return params[0];
+ }
+ }
+ return null;
+ }
+
+ /**
+ * If a Type is a class, return it as a class.
+ * If it is a ParameterizedType, return the raw type as a class.
+ * Otherwise return null.
+ * @param type
+ * @return
+ */
+ public static Class<?> getTypeRelatedClass(Type type) {
+ Class<?> directClass = getTypeClass(type, false);
+ if (directClass != null) {
+ return directClass;
+ }
+
+ if (type instanceof ParameterizedType) {
+ ParameterizedType pType = (ParameterizedType) type;
+ return getTypeRelatedClass(pType.getRawType());
+ }
+ return null;
+ }
}
Modified: cxf/trunk/rt/databinding/aegis/src/main/java/org/apache/cxf/aegis/type/XMLTypeCreator.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/databinding/aegis/src/main/java/org/apache/cxf/aegis/type/XMLTypeCreator.java?rev=811180&r1=811179&r2=811180&view=diff
==============================================================================
--- cxf/trunk/rt/databinding/aegis/src/main/java/org/apache/cxf/aegis/type/XMLTypeCreator.java (original)
+++ cxf/trunk/rt/databinding/aegis/src/main/java/org/apache/cxf/aegis/type/XMLTypeCreator.java Fri Sep 4 00:03:14 2009
@@ -22,8 +22,11 @@
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Method;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
import java.text.MessageFormat;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
@@ -230,7 +233,7 @@
@Override
public AegisType createEnumType(TypeClassInfo info) {
- Element mapping = findMapping(info.getTypeClass());
+ Element mapping = findMapping(info.getType());
if (mapping != null) {
return super.createEnumType(info);
} else {
@@ -240,7 +243,10 @@
@Override
public AegisType createCollectionType(TypeClassInfo info) {
- if (info.getGenericType() instanceof Class || info.getGenericType() instanceof TypeClassInfo) {
+ /* If it is a parameterized type, then we already know
+ * the parameter(s) and we don't need to fish them out of the XML.
+ */
+ if (info.getType() instanceof Class) {
return createCollectionTypeFromGeneric(info);
}
@@ -260,14 +266,22 @@
}
TypeClassInfo info = new TypeClassInfo();
- info.setTypeClass(pd.getReadMethod().getReturnType());
+ Type returnType = pd.getReadMethod().getGenericReturnType();
+ info.setType(returnType);
info.setDescription("property " + pd.getDisplayName());
readMetadata(info, mapping, propertyEl);
return info;
}
- protected Element findMapping(Class clazz) {
+ protected Element findMapping(Type type) {
+ // We are not prepared to find .aegis.xml files for Parameterized types.
+
+ Class<?> clazz = TypeUtil.getTypeClass(type, false);
+
+ if (clazz == null) {
+ return null;
+ }
Document doc = getDocument(clazz);
if (doc == null) {
return null;
@@ -283,8 +297,12 @@
return mapping;
}
- protected List<Element> findMappings(Class clazz) {
+ protected List<Element> findMappings(Type type) {
+ Class clazz = TypeUtil.getTypeClass(type, false);
List<Element> mappings = new ArrayList<Element>();
+ if (clazz == null) {
+ return mappings;
+ }
Element top = findMapping(clazz);
if (top != null) {
@@ -321,8 +339,9 @@
@Override
public AegisType createDefaultType(TypeClassInfo info) {
- Element mapping = findMapping(info.getTypeClass());
- List mappings = findMappings(info.getTypeClass());
+ Element mapping = findMapping(info.getType());
+ List<Element> mappings = findMappings(info.getType());
+ Class<?> relatedClass = TypeUtil.getTypeRelatedClass(info.getType());
if (mapping != null || mappings.size() > 0) {
String typeNameAtt = null;
@@ -340,8 +359,7 @@
extensibleAttributes = mapping.getAttribute("extensibleAttributes");
}
- String defaultNS = NamespaceHelper.makeNamespaceFromClassName(info.getTypeClass().getName(),
- "http");
+ String defaultNS = NamespaceHelper.makeNamespaceFromClassName(relatedClass.getName(), "http");
QName name = null;
if (typeNameAtt != null) {
name = NamespaceHelper.createQName(mapping, typeNameAtt, defaultNS);
@@ -349,7 +367,8 @@
defaultNS = name.getNamespaceURI();
}
- XMLBeanTypeInfo btinfo = new XMLBeanTypeInfo(info.getTypeClass(), mappings, defaultNS);
+ // We do not deal with Generic beans at this point.
+ XMLBeanTypeInfo btinfo = new XMLBeanTypeInfo(relatedClass, mappings, defaultNS);
btinfo.setTypeMapping(getTypeMapping());
btinfo.setDefaultMinOccurs(getConfiguration().getDefaultMinOccurs());
btinfo.setDefaultNillable(getConfiguration().isDefaultNillable());
@@ -371,12 +390,12 @@
BeanType type = new BeanType(btinfo);
if (name == null) {
- name = createQName(info.getTypeClass());
+ name = createQName(relatedClass);
}
type.setSchemaType(name);
- type.setTypeClass(info.getTypeClass());
+ type.setTypeClass(info.getType());
type.setTypeMapping(getTypeMapping());
return type;
@@ -425,7 +444,7 @@
// no mapping for this method
return info;
}
- info.setTypeClass(m.getParameterTypes()[index]);
+ info.setType(m.getGenericParameterTypes()[index]);
// info.setAnnotations(m.getParameterAnnotations()[index]);
Element parameter = getMatch(bestMatch, "parameter[@index='" + index + "']");
readMetadata(info, mapping, parameter);
@@ -440,7 +459,7 @@
// no mapping for this method
return info;
}
- info.setTypeClass(m.getReturnType());
+ info.setType(m.getGenericReturnType());
// info.setAnnotations(m.getAnnotations());
Element rtElement = DOMUtils.getFirstChildWithName(bestMatch, "", "return-type");
readMetadata(info, mapping, rtElement);
@@ -453,9 +472,23 @@
info.setTypeName(createQName(parameter, DOMUtils.getAttributeValueEmptyNull(parameter, "typeName")));
info.setMappedName(createQName(parameter,
DOMUtils.getAttributeValueEmptyNull(parameter, "mappedName")));
- setComponentType(info, mapping, parameter);
- setKeyType(info, mapping, parameter);
- setValueType(info, mapping, parameter);
+ Class<?> relatedClass = TypeUtil.getTypeRelatedClass(info.getType());
+ // we only mess with the generic issues for list and map
+ if (Collection.class.isAssignableFrom(relatedClass)) {
+ Type componentType = getComponentType(mapping, parameter);
+ Type fullType = ParameterizedTypeFactory.createParameterizedType(relatedClass,
+ new Type[] {componentType});
+ info.setType(fullType);
+ } else if (Map.class.isAssignableFrom(relatedClass)) {
+ Type keyType = getKeyType(mapping, parameter);
+ info.setKeyType(keyType);
+ Type valueType = getValueType(mapping, parameter);
+ info.setValueType(valueType);
+ Type fullType = ParameterizedTypeFactory.createParameterizedType(relatedClass,
+ new Type[] {keyType, valueType});
+ info.setType(fullType);
+
+ }
setType(info, parameter);
String min = DOMUtils.getAttributeValueEmptyNull(parameter, "minOccurs");
@@ -482,8 +515,8 @@
@Override
protected AegisType getOrCreateGenericType(TypeClassInfo info) {
AegisType type = null;
- if (info.getGenericType() != null) {
- type = createTypeFromGeneric(info.getGenericType());
+ if (info.getType() instanceof ParameterizedType) {
+ type = createTypeFromGeneric(info.getType());
}
if (type == null) {
@@ -520,7 +553,8 @@
@Override
protected AegisType getOrCreateMapValueType(TypeClassInfo info) {
AegisType type = null;
- if (info.getGenericType() != null) {
+ if (info.getType() instanceof ParameterizedType) {
+ // well, let's hope that someone has filled in the value type.
type = createTypeFromGeneric(info.getValueType());
}
@@ -531,14 +565,32 @@
return type;
}
- protected void setComponentType(TypeClassInfo info, Element mapping, Element parameter) {
- String componentType = DOMUtils.getAttributeValueEmptyNull(parameter, "componentType");
- if (componentType != null) {
- info.setGenericType(loadGeneric(info, mapping, componentType));
+ private Type getComponentType(Element mapping, Element parameter) {
+ String componentSpec = DOMUtils.getAttributeValueEmptyNull(parameter, "componentType");
+ if (componentSpec == null) {
+ return null;
}
+ return getGenericParameterFromSpec(mapping, componentSpec);
+ }
+
+ private Type getKeyType(Element mapping, Element parameter) {
+ String spec = DOMUtils.getAttributeValueEmptyNull(parameter, "keyType");
+ if (spec == null) {
+ return null;
+ }
+ return getGenericParameterFromSpec(mapping, spec);
+ }
+
+ private Type getValueType(Element mapping, Element parameter) {
+ String spec = DOMUtils.getAttributeValueEmptyNull(parameter, "valueType");
+ if (spec == null) {
+ return null;
+ }
+ return getGenericParameterFromSpec(mapping, spec);
}
- private Object loadGeneric(TypeClassInfo info, Element mapping, String componentType) {
+ // This cannot do List<List<x>>.
+ private Type getGenericParameterFromSpec(Element mapping, String componentType) {
if (componentType.startsWith("#")) {
String name = componentType.substring(1);
Element propertyEl = getMatch(mapping, "./component[@name='" + name + "']");
@@ -547,18 +599,13 @@
+ "'");
}
- TypeClassInfo componentInfo = new TypeClassInfo();
- componentInfo.setDescription("generic component " + componentInfo.getDescription());
- readMetadata(componentInfo, mapping, propertyEl);
String className = DOMUtils.getAttributeValueEmptyNull(propertyEl, "class");
if (className == null) {
throw new DatabindingException("A 'class' attribute must be specified for <component> "
+ name);
}
-
- componentInfo.setTypeClass(loadComponentClass(className));
-
- return componentInfo;
+
+ return loadComponentClass(className);
} else {
return loadComponentClass(componentType);
}
@@ -584,19 +631,7 @@
}
}
- protected void setKeyType(TypeClassInfo info, Element mapping, Element parameter) {
- String componentType = DOMUtils.getAttributeValueEmptyNull(parameter, "keyType");
- if (componentType != null) {
- info.setKeyType(loadGeneric(info, mapping, componentType));
- }
- }
- private void setValueType(TypeClassInfo info, Element mapping, Element parameter) {
- String componentType = DOMUtils.getAttributeValueEmptyNull(parameter, "valueType");
- if (componentType != null) {
- info.setValueType(loadGeneric(info, mapping, componentType));
- }
- }
private Element getBestMatch(Element mapping, Method method, List<Element> availableNodes) {
// first find all the matching method names
Modified: cxf/trunk/rt/databinding/aegis/src/main/java/org/apache/cxf/aegis/type/java5/Java5TypeCreator.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/databinding/aegis/src/main/java/org/apache/cxf/aegis/type/java5/Java5TypeCreator.java?rev=811180&r1=811179&r2=811180&view=diff
==============================================================================
--- cxf/trunk/rt/databinding/aegis/src/main/java/org/apache/cxf/aegis/type/java5/Java5TypeCreator.java (original)
+++ cxf/trunk/rt/databinding/aegis/src/main/java/org/apache/cxf/aegis/type/java5/Java5TypeCreator.java Fri Sep 4 00:03:14 2009
@@ -21,6 +21,7 @@
import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
import java.lang.reflect.WildcardType;
import java.util.Collection;
import java.util.Map;
@@ -31,6 +32,7 @@
import org.apache.cxf.aegis.type.AbstractTypeCreator;
import org.apache.cxf.aegis.type.AegisType;
import org.apache.cxf.aegis.type.TypeClassInfo;
+import org.apache.cxf.aegis.type.TypeUtil;
import org.apache.cxf.aegis.type.basic.BeanType;
import org.apache.cxf.aegis.util.NamespaceHelper;
import org.apache.cxf.aegis.util.ServiceUtils;
@@ -61,18 +63,16 @@
public TypeClassInfo createClassInfo(Method m, int index) {
if (index >= 0) {
TypeClassInfo info;
- java.lang.reflect.Type genericType = m.getGenericParameterTypes()[index];
+ Type genericType = m.getGenericParameterTypes()[index];
if (genericType instanceof Class) {
info = nextCreator.createClassInfo(m, index);
} else {
info = new TypeClassInfo();
info.setDescription("method " + m.getName() + " parameter " + index);
- info.setGenericType(genericType);
+ info.setType(genericType);
}
- info.setTypeClass(m.getParameterTypes()[index]);
Class paramTypeClass = annotationReader.getParamType(m, index);
-
info.setAegisTypeClass(castToAegisTypeClass(paramTypeClass));
String paramName = annotationReader.getParamName(m, index);
@@ -84,18 +84,16 @@
return info;
} else {
- java.lang.reflect.Type genericReturnType = m.getGenericReturnType();
+ Type genericReturnType = m.getGenericReturnType();
TypeClassInfo info;
if (genericReturnType instanceof Class) {
info = nextCreator.createClassInfo(m, index);
} else {
info = new TypeClassInfo();
info.setDescription("method " + m.getName() + " parameter " + index);
- info.setGenericType(genericReturnType);
+ info.setType(genericReturnType);
}
- info.setTypeClass(m.getReturnType());
-
if (m.getParameterAnnotations() != null && m.getAnnotations().length > 0) {
info.setAnnotations(m.getAnnotations());
}
@@ -113,10 +111,14 @@
}
}
+ /*
+ * Apparently, this callers must notice collection types and not call this.
+ */
@Override
public TypeClassInfo createClassInfo(PropertyDescriptor pd) {
+ Type genericType = pd.getReadMethod().getGenericReturnType();
TypeClassInfo info = createBasicClassInfo(pd.getPropertyType());
- info.setGenericType(pd.getReadMethod().getGenericReturnType());
+ info.setType(genericType); // override basicClassInfo's of the type.
info.setAnnotations(pd.getReadMethod().getAnnotations());
info.setAegisTypeClass(castToAegisTypeClass(annotationReader.getType(pd.getReadMethod())));
@@ -125,109 +127,95 @@
@Override
public AegisType createCollectionType(TypeClassInfo info) {
- Object genericType = info.getGenericType();
- Class paramClass = getComponentType(genericType, 0);
+ Type type = info.getType();
+
+ Type componentType = getComponentType(type, 0);
- if (paramClass != null) {
+ if (componentType != null) {
return createCollectionTypeFromGeneric(info);
} else {
return nextCreator.createCollectionType(info);
}
}
+ // should be called 'collection'
protected AegisType getOrCreateGenericType(TypeClassInfo info) {
- return getOrCreateParameterizedType(info.getGenericType(), 0);
+ return getOrCreateParameterizedType(info.getType(), 0);
}
protected AegisType getOrCreateMapKeyType(TypeClassInfo info) {
- return getOrCreateParameterizedType(info.getGenericType(), 0);
+ return getOrCreateParameterizedType(info.getType(), 0);
}
protected AegisType getOrCreateMapValueType(TypeClassInfo info) {
- return getOrCreateParameterizedType(info.getGenericType(), 1);
+ return getOrCreateParameterizedType(info.getType(), 1);
}
- protected AegisType getOrCreateParameterizedType(Object generic, int index) {
- Class clazz = getComponentType(generic, index);
+ protected AegisType getOrCreateParameterizedType(Type generic, int index) {
+ Type paramType = getComponentType(generic, index);
+ if (paramType == null) {
+ return createObjectType();
+ }
+
+ /* null arises when the index-th parameter to generic is something list List<T> */
+ Class clazz = TypeUtil.getTypeRelatedClass(paramType);
if (clazz == null) {
return createObjectType();
}
- if (!Collection.class.isAssignableFrom(clazz) && !Map.class.isAssignableFrom(clazz)) {
+ // here is where we insist that we only deal with collection types.
+
+ if (!Collection.class.isAssignableFrom(clazz)
+ && !Map.class.isAssignableFrom(clazz)) {
return getTopCreator().createType(clazz);
}
- Object component = getGenericComponent(generic, index);
-
TypeClassInfo info = createBasicClassInfo(clazz);
info.setDescription(clazz.toString());
- info.setGenericType(component);
+ info.setType(paramType);
AegisType type = createTypeForClass(info);
return type;
}
- private Object getGenericComponent(Object genericType, int index) {
- if (genericType instanceof ParameterizedType) {
- ParameterizedType type = (ParameterizedType)genericType;
-
- if (type.getActualTypeArguments()[index] instanceof WildcardType) {
- WildcardType wildcardType = (WildcardType)type.getActualTypeArguments()[index];
-
- return wildcardType;
- } else if (type.getActualTypeArguments()[index] instanceof ParameterizedType) {
- ParameterizedType ptype = (ParameterizedType)type.getActualTypeArguments()[index];
-
- return ptype;
- }
- }
-
- return null;
- }
-
- protected Class getComponentType(Object genericType, int index) {
- Class paramClass = null;
-
+ protected Type getComponentType(Type genericType, int index) {
if (genericType instanceof ParameterizedType) {
ParameterizedType type = (ParameterizedType)genericType;
-
- if (type.getActualTypeArguments()[index] instanceof Class) {
- paramClass = (Class)type.getActualTypeArguments()[index];
- } else if (type.getActualTypeArguments()[index] instanceof WildcardType) {
- WildcardType wildcardType = (WildcardType)type.getActualTypeArguments()[index];
+ Type paramType = type.getActualTypeArguments()[index];
+ if (paramType instanceof WildcardType) {
+ WildcardType wildcardType = (WildcardType)paramType;
// we really aren't prepared to deal with multiple upper bounds,
// so we just look at the first one.
- if (wildcardType.getUpperBounds()[0] instanceof Class) {
- paramClass = (Class)wildcardType.getUpperBounds()[0];
- }
- } else if (type.getActualTypeArguments()[index] instanceof ParameterizedType) {
- ParameterizedType ptype = (ParameterizedType)type.getActualTypeArguments()[index];
- paramClass = (Class)ptype.getRawType();
+ return wildcardType.getUpperBounds()[0];
+ } else {
+ return paramType; // take our chances.
}
+ } else {
+ throw new DatabindingException("Type " + genericType + " is not a generic.");
}
- return paramClass;
}
@Override
public AegisType createDefaultType(TypeClassInfo info) {
QName typeName = info.getTypeName();
+ Class<?> relatedClass = TypeUtil.getTypeRelatedClass(info.getType());
if (typeName == null) {
- typeName = createQName(info.getTypeClass());
+ typeName = createQName(relatedClass);
}
AnnotatedTypeInfo typeInfo = new AnnotatedTypeInfo(
getTypeMapping(),
- info.getTypeClass(),
+ relatedClass,
typeName.getNamespaceURI(),
getConfiguration());
typeInfo.setExtensibleElements(annotationReader.isExtensibleElements(
- info.getTypeClass(),
+ relatedClass,
getConfiguration().isDefaultExtensibleElements()));
typeInfo.setExtensibleAttributes(annotationReader.isExtensibleAttributes(
- info.getTypeClass(),
+ relatedClass,
getConfiguration().isDefaultExtensibleAttributes()));
typeInfo.setDefaultMinOccurs(getConfiguration().getDefaultMinOccurs());
@@ -244,8 +232,8 @@
public AegisType createEnumType(TypeClassInfo info) {
EnumType type = new EnumType();
- type.setSchemaType(createQName(info.getTypeClass()));
- type.setTypeClass(info.getTypeClass());
+ type.setSchemaType(createQName(TypeUtil.getTypeRelatedClass(info.getType())));
+ type.setTypeClass(info.getType());
type.setTypeMapping(getTypeMapping());
return type;