Author: sagara Date: Tue Jul 5 11:25:06 2011 New Revision: 1142991 URL: http://svn.apache.org/viewvc?rev=1142991&view=rev Log: AXIS2-5064 - Implemented basic Java Map Support.
Modified: axis/axis2/java/core/trunk/modules/adb/src/ (props changed) axis/axis2/java/core/trunk/modules/adb/src/org/apache/axis2/databinding/typemapping/SimpleTypeMapper.java axis/axis2/java/core/trunk/modules/adb/src/org/apache/axis2/databinding/utils/BeanUtil.java axis/axis2/java/core/trunk/modules/adb/src/org/apache/axis2/rpc/receivers/RPCUtil.java axis/axis2/java/core/trunk/modules/adb/test/org/apache/axis2/databinding/utils/BeanUtilTest.java axis/axis2/java/core/trunk/modules/kernel/src/org/apache/axis2/Constants.java axis/axis2/java/core/trunk/modules/kernel/src/org/apache/axis2/description/java2wsdl/DefaultSchemaGenerator.java axis/axis2/java/core/trunk/modules/kernel/src/org/apache/axis2/description/java2wsdl/DocLitBareSchemaGenerator.java axis/axis2/java/core/trunk/modules/kernel/src/org/apache/axis2/description/java2wsdl/TypeTable.java Propchange: axis/axis2/java/core/trunk/modules/adb/src/ ------------------------------------------------------------------------------ --- svn:ignore (added) +++ svn:ignore Tue Jul 5 11:25:06 2011 @@ -0,0 +1 @@ +META-INF Modified: axis/axis2/java/core/trunk/modules/adb/src/org/apache/axis2/databinding/typemapping/SimpleTypeMapper.java URL: http://svn.apache.org/viewvc/axis/axis2/java/core/trunk/modules/adb/src/org/apache/axis2/databinding/typemapping/SimpleTypeMapper.java?rev=1142991&r1=1142990&r2=1142991&view=diff ============================================================================== --- axis/axis2/java/core/trunk/modules/adb/src/org/apache/axis2/databinding/typemapping/SimpleTypeMapper.java (original) +++ axis/axis2/java/core/trunk/modules/adb/src/org/apache/axis2/databinding/typemapping/SimpleTypeMapper.java Tue Jul 5 11:25:06 2011 @@ -384,5 +384,15 @@ public class SimpleTypeMapper { public static boolean isDomDocument(Class classType) { return Document.class.isAssignableFrom(classType); } + + /** + * Checks weather passed parameter class is a java.util.Map + * + * @param classType the class type + * @return true, if it is a map + */ + public static boolean isMap(Class classType){ + return java.util.Map.class.isAssignableFrom(classType); + } } Modified: axis/axis2/java/core/trunk/modules/adb/src/org/apache/axis2/databinding/utils/BeanUtil.java URL: http://svn.apache.org/viewvc/axis/axis2/java/core/trunk/modules/adb/src/org/apache/axis2/databinding/utils/BeanUtil.java?rev=1142991&r1=1142990&r2=1142991&view=diff ============================================================================== --- axis/axis2/java/core/trunk/modules/adb/src/org/apache/axis2/databinding/utils/BeanUtil.java (original) +++ axis/axis2/java/core/trunk/modules/adb/src/org/apache/axis2/databinding/utils/BeanUtil.java Tue Jul 5 11:25:06 2011 @@ -271,7 +271,25 @@ public class BeanUtil { beanName, processingDocLitBare); propertyQnameValueList.add(value); } - } else { + } else if (SimpleTypeMapper.isMap(ptype)) { + OMFactory fac = OMAbstractFactory.getOMFactory(); + QName qNamefortheType = (QName) typeTable + .getComplexSchemaMap().get(getClassName(beanClass)); + OMNamespace ns = fac.createOMNamespace( + qNamefortheType.getNamespaceURI(), + qNamefortheType.getPrefix()); + List<OMElement> mapEntries = getMapElement(fac, + ptype, (Map) value, typeTable, qualified); + OMElement map = fac.createOMElement(propertyName, + qNamefortheType.getNamespaceURI(), + qNamefortheType.getPrefix()); + for (OMElement ele : mapEntries) { + map.addChild(ele); + } + addTypeQname(elemntNameSpace, propertyQnameValueList, + property, beanName, processingDocLitBare); + propertyQnameValueList.add(map); + } else { addTypeQname(elemntNameSpace, propertyQnameValueList, property, beanName, processingDocLitBare); if (Object.class.equals(ptype)) { @@ -280,13 +298,25 @@ public class BeanUtil { QName qNamefortheType = (QName) typeTable .getComplexSchemaMap().get( getClassName(beanClass)); - OMFactory fac = OMAbstractFactory.getOMFactory(); - OMElement element = fac - .createOMElement(new QName(elemntNameSpace - .getNamespaceURI(), property.getName(), - qNamefortheType.getPrefix())); - element.addChild(fac.createOMText(SimpleTypeMapper - .getStringValue(value))); + OMFactory fac = OMAbstractFactory.getOMFactory(); + QName elementName = new QName(elemntNameSpace + .getNamespaceURI(), property.getName(), + qNamefortheType.getPrefix()); + OMElement element; + if(SimpleTypeMapper.isSimpleType(value)){ + element = fac.createOMElement(elementName); + element.addChild(fac.createOMText(SimpleTypeMapper + .getStringValue(value))); + }else{ + XMLStreamReader xr = BeanUtil.getPullParser(value, + elementName, typeTable, true, false); + OMXMLParserWrapper stAXOMBuilder = + OMXMLBuilderFactory.createStAXOMBuilder( + OMAbstractFactory.getOMFactory(), new StreamWrapper(xr)); + element = stAXOMBuilder.getDocumentElement(); + + + } addInstanceTypeAttribute(fac, element, value, typeTable); propertyQnameValueList.add(element); continue; @@ -503,6 +533,19 @@ public class BeanUtil { } else if (parameters.isArray()) { partObj = deserialize(parameters, (OMElement) parts.getParent(), objectSupplier, prty.getName()); + } else if (SimpleTypeMapper.isMap(parameters)){ + partObj = null; + final Type type = prty.getReadMethod().getGenericReturnType(); + if (type instanceof ParameterizedType) { + ParameterizedType aType = (ParameterizedType) type; + Type[] parameterArgTypes = aType.getActualTypeArguments(); + partObj = processGenericsMapElement(parameterArgTypes + , (OMElement) parts.getParent(), null, parts.getChildren(), objectSupplier, beanClass); + } else { + Type[] parameterArgTypes = {Object.class,Object.class}; + partObj = processGenericsMapElement(parameterArgTypes + , (OMElement) parts.getParent(), null, parts.getChildren(), objectSupplier, beanClass); + } } else { partObj = deserialize(parameters, parts, objectSupplier, null); } @@ -863,6 +906,21 @@ public class BeanUtil { } else if(SimpleTypeMapper.isDomDocument(classType)){ return convertOMtoDOM(omElement); + } else if(SimpleTypeMapper.isMap(classType)){ + if (generictype != null && (generictype instanceof ParameterizedType)) { + ParameterizedType aType = (ParameterizedType) generictype; + Type[] parameterArgTypes = aType.getActualTypeArguments(); + Iterator parts = omElement.getChildElements(); + return processGenericsMapElement(parameterArgTypes + , omElement, helper, parts, objectSupplier, generictype); + } else { + Type[] parameterArgTypes = {Object.class,Object.class}; + Iterator parts = omElement.getChildElements(); + return processGenericsMapElement(parameterArgTypes, + omElement, helper, parts, objectSupplier, generictype); + } + + } else { return BeanUtil.deserialize(classType, omElement, objectSupplier, null); } @@ -1059,8 +1117,8 @@ public class BeanUtil { Constants.DEFAULT_XSD_NAMESPACE_PREFIX); element.declareNamespace(xsiNS); element.declareNamespace(xsdNS); - QName xsdType = typeTable.getSimpleSchemaTypeName(resObject.getClass() - .getName()); + QName xsdType = typeTable.getSchemaTypeName(resObject.getClass() + .getName()); String attrValue = xsdType.getPrefix() + ":" + xsdType.getLocalPart(); element.addAttribute(Constants.XSI_TYPE_ATTRIBUTE, attrValue, xsiNS); } @@ -1164,5 +1222,242 @@ public class BeanUtil { return curr; } + /** + * This method deserialize OM model in to a instance of java.util.Map + * + * @param parameterArgTypes the parameter argument types of Map <k,V> + * @param omElement the OMElement + * @param helper the helper + * @param parts the parts + * @param objectSupplier the object supplier + * @param genericType the generic type + * @return a instance of java.util.Map + * @throws AxisFault the axis fault + */ + private static Map<Object,Object> processGenericsMapElement(Type[] parameterArgTypes, + OMElement omElement, MultirefHelper helper, Iterator parts, + ObjectSupplier objectSupplier, Type genericType) throws AxisFault { + Object objValue; + Map<Object,Object> valueMap = getMapInstance(genericType) ; + while (parts.hasNext()) { + objValue = parts.next(); + if (objValue instanceof OMElement) { + omElement = (OMElement) objValue; + } else { + continue; + } + + if(omElement != null){ + Iterator entryParts = omElement.getChildren(); + Object entryKey = null; + Object entryValue = null; + while (entryParts.hasNext()) { + objValue = entryParts.next(); + if (objValue instanceof OMElement) { + omElement = (OMElement) objValue; + } else { + continue; + } + if (omElement.getLocalName().equals( + org.apache.axis2.Constants.MAP_KEY_ELEMENT_NAME)) { + entryKey = processMapParameterObject( parameterArgTypes[0], omElement, + helper, objectSupplier, genericType); + continue; + } + if (omElement.getLocalName().equals( + org.apache.axis2.Constants.MAP_VALUE_ELEMENT_NAME)) { + entryValue = processMapParameterObject( parameterArgTypes[1], + omElement, helper, objectSupplier, genericType); + continue; + } + } + if(entryKey != null){ + valueMap.put(entryKey, entryValue); + } + } + + } + return valueMap; + } + + + /** + * This method convert a instance of java.util.Map into + * OM object model for serialization. + * + * @param fac the OMFactory + * @param type of the java.util.Map + * @param results the results values + * @param typeTable the type table + * @param elementFormDefault the element form default + * @return list of OMElement + */ + public static List<OMElement> getMapElement(OMFactory fac, Type type, + Map results, TypeTable typeTable, boolean elementFormDefault) { + Iterator<Object> keyItr = results.keySet().iterator(); + List<OMElement> list = new ArrayList<OMElement>(); + OMNamespace ns = fac.createOMNamespace( + org.apache.axis2.Constants.AXIS2_MAP_NAMESPACE_URI, + org.apache.axis2.Constants.AXIS2_MAP_NAMESPACE_PREFIX); + Type keyType = Object.class; + Type valueType = Object.class; + if (type instanceof ParameterizedType) { + ParameterizedType aType = (ParameterizedType) type; + Type[] parameterArgTypes = aType.getActualTypeArguments(); + keyType = parameterArgTypes[0]; + valueType = parameterArgTypes[1]; + } + while (keyItr.hasNext()) { + OMElement omEntry; + Object key = keyItr.next(); + Object value; + if (key != null) { + value = results.get(key); + List<Object> properties = new ArrayList<Object>(); + + key = getMapParameterElement(fac, + org.apache.axis2.Constants.MAP_KEY_ELEMENT_NAME, key, + keyType, typeTable, ns, elementFormDefault); + properties.add(new QName(ns.getNamespaceURI(), + org.apache.axis2.Constants.MAP_KEY_ELEMENT_NAME, ns + .getPrefix())); + properties.add(key); + + value = getMapParameterElement(fac, + org.apache.axis2.Constants.MAP_VALUE_ELEMENT_NAME, + value, valueType, typeTable, ns, elementFormDefault); + properties.add(new QName(ns.getNamespaceURI(), + org.apache.axis2.Constants.MAP_VALUE_ELEMENT_NAME, ns + .getPrefix())); + properties.add(value); + + XMLStreamReader pullParser = new ADBXMLStreamReaderImpl( + new QName( + ns.getNamespaceURI(), + org.apache.axis2.Constants.MAP_ENTRY_ELEMENT_NAME, + ns.getPrefix()), properties.toArray(), null, + typeTable, elementFormDefault); + + StAXOMBuilder stAXOMBuilder = new StAXOMBuilder( + OMAbstractFactory.getOMFactory(), new StreamWrapper( + pullParser)); + omEntry = stAXOMBuilder.getDocumentElement(); + list.add(omEntry); + } + } + return list; + } + + /** + * Helper method to deserialize each parameter of Map. + * + * @param paraType the parameter type + * @param omElement the OMElement + * @param helper the helper + * @param objectSupplier the object supplier + * @param genericType the generic type + * @return the object + * @throws AxisFault the axis fault + */ + private static Object processMapParameterObject(Type paraType, OMElement omElement, + MultirefHelper helper, ObjectSupplier objectSupplier, + Type genericType) throws AxisFault { + if (paraType instanceof ParameterizedType) { + if (Map.class.isAssignableFrom((Class) + ((ParameterizedType) paraType).getRawType())) { + return processGenericsMapElement( + ((ParameterizedType) paraType).getActualTypeArguments(), + omElement, helper, omElement.getChildren(), + objectSupplier, paraType); + } else if (Collection.class .isAssignableFrom((Class) + ((ParameterizedType) paraType).getRawType())) { + //TODO + return null; + } else { + // TODO - support for custom ParameterizedTypes + return null; + } + + } else { + return processObject(omElement, (Class) paraType, helper, true, + objectSupplier, genericType); + } + } + + /** + * This method instantiate a Map instance according to the expected + * parameter type of the service method. a instance HashMap<Object, Object> + * returns as the default value and in case of Exception. + * + * @param genericType the generic type + * @return the map instance + */ + private static Map<Object, Object> getMapInstance(Type genericType) { + Class rowType; + if (genericType instanceof ParameterizedType) { + rowType = (Class) ((ParameterizedType) genericType).getRawType(); + } else { + rowType = (Class) genericType; + } + + if (Map.class.getName().equals(rowType.getName())) { + return new HashMap<Object, Object>(); + } else { + try { + return (Map<Object, Object>) rowType.newInstance(); + } catch (Exception e) { + return new HashMap<Object, Object>(); + } + } + } + + /** + * Process the provided return value and constructs OMElement accordingly. + * + * @param fac the OMFactory instance + * @param elementName the element name for return OMElement + * @param value the actual return value + * @param valueType the value type of return value + * @param typeTable the type table + * @param ns the OMNamespace + * @param elementFormDefault the element form default + * @return the map parameter object + */ + private static Object getMapParameterElement(OMFactory fac, + String elementName, Object value, Type valueType, + TypeTable typeTable, OMNamespace ns, boolean elementFormDefault) { + //TODO - key/value can be a Collection, Array , Dom document ,OMElement etc + if (SimpleTypeMapper.isMap(value.getClass())) { + List<OMElement> childList = getMapElement(fac, valueType, + (Map) value, typeTable, elementFormDefault); + OMElement omValue = fac.createOMElement(elementName, + ns.getNamespaceURI(), ns.getPrefix()); + for (OMElement child : childList) { + omValue.addChild(child); + } + return omValue; + + } else if (SimpleTypeMapper.isObjectType((Class) valueType)) { + OMElement omValue; + omValue = fac.createOMElement(elementName, ns); + if (SimpleTypeMapper.isSimpleType(value)) { + omValue.addChild(fac.createOMText(SimpleTypeMapper + .getStringValue(value))); + } else { + QName name = new QName(ns.getNamespaceURI(), elementName, + ns.getPrefix()); + XMLStreamReader xr = BeanUtil.getPullParser(value, name, + typeTable, true, false); + OMXMLParserWrapper stAXOMBuilder = OMXMLBuilderFactory + .createStAXOMBuilder(OMAbstractFactory.getOMFactory(), + new StreamWrapper(xr)); + omValue = stAXOMBuilder.getDocumentElement(); + + } + addInstanceTypeAttribute(fac, omValue, value, typeTable); + return omValue; + } + return value; + } } Modified: axis/axis2/java/core/trunk/modules/adb/src/org/apache/axis2/rpc/receivers/RPCUtil.java URL: http://svn.apache.org/viewvc/axis/axis2/java/core/trunk/modules/adb/src/org/apache/axis2/rpc/receivers/RPCUtil.java?rev=1142991&r1=1142990&r2=1142991&view=diff ============================================================================== --- axis/axis2/java/core/trunk/modules/adb/src/org/apache/axis2/rpc/receivers/RPCUtil.java (original) +++ axis/axis2/java/core/trunk/modules/adb/src/org/apache/axis2/rpc/receivers/RPCUtil.java Tue Jul 5 11:25:06 2011 @@ -46,6 +46,9 @@ import java.lang.reflect.Array; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.Collection; +import java.util.Iterator; +import java.util.List; +import java.util.Map; public class RPCUtil { @@ -322,7 +325,22 @@ public class RPCUtil { service.isElementFormDefault(), service.getTypeTable()); envelope.getBody().addChild(bodyChild); - } else if (SimpleTypeMapper.isDataHandler(resObject.getClass())) { + + } else if (SimpleTypeMapper.isMap(resObject.getClass())) { + OMElement resElemt = fac.createOMElement( + partName, ns); + List<OMElement> omList = BeanUtil.getMapElement(fac, + method.getGenericReturnType(), (Map) resObject, + service.getTypeTable(), + service.isElementFormDefault()); + Iterator<OMElement> omItr = omList.iterator(); + while (omItr.hasNext()) { + resElemt.addChild(omItr.next()); + } + envelope.getBody().addChild(resElemt); + + } else if (SimpleTypeMapper.isDataHandler(resObject + .getClass())) { OMElement resElemt; if (service.isElementFormDefault()) { resElemt = fac.createOMElement(partName, ns); @@ -477,6 +495,22 @@ public class RPCUtil { service.isElementFormDefault(), service.getTypeTable()); envelope.getBody().addChild(bodyChild); + } else if (SimpleTypeMapper.isMap(resObject.getClass())){ + OMElement resElemt = fac.createOMElement(method.getName() + "Response", ns); + List<OMElement> omList = BeanUtil.getMapElement(fac,method.getGenericReturnType(), (Map) resObject,service.getTypeTable(),service.isElementFormDefault()); + OMElement returnElement; + if (service.isElementFormDefault()) { + returnElement = fac.createOMElement(RETURN_WRAPPER, ns); + } else { + returnElement = fac.createOMElement(RETURN_WRAPPER, null); + } + Iterator<OMElement> omItr = omList.iterator(); + while(omItr.hasNext()){ + returnElement.addChild(omItr.next()); + } + resElemt.addChild(returnElement); + envelope.getBody().addChild(resElemt); + } else if (SimpleTypeMapper.isDataHandler(resObject.getClass())) { OMElement resElemt = fac.createOMElement(method.getName() + "Response", ns); OMText text = fac.createOMText(resObject, true); Modified: axis/axis2/java/core/trunk/modules/adb/test/org/apache/axis2/databinding/utils/BeanUtilTest.java URL: http://svn.apache.org/viewvc/axis/axis2/java/core/trunk/modules/adb/test/org/apache/axis2/databinding/utils/BeanUtilTest.java?rev=1142991&r1=1142990&r2=1142991&view=diff ============================================================================== --- axis/axis2/java/core/trunk/modules/adb/test/org/apache/axis2/databinding/utils/BeanUtilTest.java (original) +++ axis/axis2/java/core/trunk/modules/adb/test/org/apache/axis2/databinding/utils/BeanUtilTest.java Tue Jul 5 11:25:06 2011 @@ -37,6 +37,7 @@ import javax.xml.namespace.QName; import java.io.ByteArrayInputStream; import java.math.BigInteger; import java.util.List; +import java.util.Map; public class BeanUtilTest extends TestCase { @@ -254,6 +255,22 @@ public class BeanUtilTest extends TestCa } + public void testProcessSimpleMap() throws Exception { + OMNamespace ns = omFactory.createOMNamespace(org.apache.axis2.Constants.AXIS2_MAP_NAMESPACE_URI, + org.apache.axis2.Constants.AXIS2_MAP_NAMESPACE_PREFIX); + OMElement entry = omFactory.createOMElement(org.apache.axis2.Constants.MAP_ENTRY_ELEMENT_NAME,ns); + OMElement key = omFactory.createOMElement(org.apache.axis2.Constants.MAP_KEY_ELEMENT_NAME,ns); + OMElement value = omFactory.createOMElement(org.apache.axis2.Constants.MAP_VALUE_ELEMENT_NAME,ns); + key.setText("key1"); + value.setText("value1"); + entry.addChild(key); + entry.addChild(value); + omElement.addChild(entry); + + Object result = BeanUtil.processObject(omElement, Map.class, new MultirefHelper(omElement), false, objectSupplier, Map.class); + assertTrue(result instanceof Map); + } + private static String toStr(ByteArrayInputStream is) { int size = is.available(); char[] theChars = new char[size]; Modified: axis/axis2/java/core/trunk/modules/kernel/src/org/apache/axis2/Constants.java URL: http://svn.apache.org/viewvc/axis/axis2/java/core/trunk/modules/kernel/src/org/apache/axis2/Constants.java?rev=1142991&r1=1142990&r2=1142991&view=diff ============================================================================== --- axis/axis2/java/core/trunk/modules/kernel/src/org/apache/axis2/Constants.java (original) +++ axis/axis2/java/core/trunk/modules/kernel/src/org/apache/axis2/Constants.java Tue Jul 5 11:25:06 2011 @@ -320,6 +320,15 @@ public class Constants extends org.apach */ public static int MAX_HIERARCHICAL_DEPTH = 10; public static final String HIDDEN_SERVICE_PARAM_NAME = "hiddenService"; + + + public static final String MAP_MAP_ELEMENT_NAME = "map"; + public static final String MAP_ENTRY_ELEMENT_NAME = "entry"; + public static final String MAP_KEY_ELEMENT_NAME = "key"; + public static final String MAP_VALUE_ELEMENT_NAME = "value"; + public static final String AXIS2_MAP_NAMESPACE_URI = + "http://ws.apache.org/namespaces/axis2/map"; + public static final String AXIS2_MAP_NAMESPACE_PREFIX = "map"; public static interface Configuration { public static final String ENABLE_REST = "enableREST"; Modified: axis/axis2/java/core/trunk/modules/kernel/src/org/apache/axis2/description/java2wsdl/DefaultSchemaGenerator.java URL: http://svn.apache.org/viewvc/axis/axis2/java/core/trunk/modules/kernel/src/org/apache/axis2/description/java2wsdl/DefaultSchemaGenerator.java?rev=1142991&r1=1142990&r2=1142991&view=diff ============================================================================== --- axis/axis2/java/core/trunk/modules/kernel/src/org/apache/axis2/description/java2wsdl/DefaultSchemaGenerator.java (original) +++ axis/axis2/java/core/trunk/modules/kernel/src/org/apache/axis2/description/java2wsdl/DefaultSchemaGenerator.java Tue Jul 5 11:25:06 2011 @@ -20,6 +20,7 @@ package org.apache.axis2.description.java2wsdl; import org.apache.axis2.AxisFault; +import org.apache.axis2.Constants; import org.apache.axis2.jaxrs.JAXRSUtils; import org.apache.axis2.jaxrs.JAXRSModel; import org.apache.axis2.util.JavaUtils; @@ -58,6 +59,12 @@ public class DefaultSchemaGenerator impl public static final String NAME_SPACE_PREFIX = "ax2";// axis2 name space private static int prefixCount = 1; + + /* This is required to get unique name for java.util.Map. + * e.g - Map<String,Map<String,Object>> outerMap; + */ + private static int mapCount = 1; + private static int entryCount = 1; private JAXRSModel classModel; @@ -391,7 +398,11 @@ public class DefaultSchemaGenerator impl if (nonRpcMethods.contains(jMethod.getName())) { generateSchemaForType(sequence, null, jMethod.getName()); break; - } else { + + } else if(methodParameter != null && Map.class.isAssignableFrom(methodParameter)) { + generateWrappedSchemaTypeForMap(sequence,genericParameterTypes[j], parameterName); + } + else { Type genericParameterType = genericParameterTypes[j]; Type genericType = null; if(genericParameterType instanceof ParameterizedType){ @@ -423,12 +434,18 @@ public class DefaultSchemaGenerator impl Type genericParameterType = jMethod.getGenericReturnType(); if (nonRpcMethods.contains(jMethod.getName())) { generateSchemaForType(sequence, null, returnName); + } else if (Map.class.isAssignableFrom(returnType)){ + if (genericParameterType instanceof ParameterizedType) { + generateWrappedSchemaTypeForMap(sequence, genericParameterType, returnName); + } else { + generateWrappedSchemaTypeForMap(sequence, returnType, returnName); + } } else if(genericParameterType instanceof ParameterizedType){ - ParameterizedType aType = (ParameterizedType) genericParameterType; - Type[] parameterArgTypes = aType.getActualTypeArguments(); - generateSchemaForType(sequence, parameterArgTypes[0], returnName, true); - } else { - generateSchemaForType(sequence, returnType, returnName); + ParameterizedType aType = (ParameterizedType) genericParameterType; + Type[] parameterArgTypes = aType.getActualTypeArguments(); + generateSchemaForType(sequence, parameterArgTypes[0], returnName, true); + } else { + generateSchemaForType(sequence, returnType, returnName); } AxisMessage outMessage = axisOperation.getMessage( @@ -646,24 +663,34 @@ public class DefaultSchemaGenerator impl if(genericFieldType instanceof ParameterizedType){ ParameterizedType aType = (ParameterizedType) genericFieldType; Type[] fieldArgTypes = aType.getActualTypeArguments(); - try { - generateSchemaforGenericFields(xmlSchema, - sequence, - fieldArgTypes[0], - propertyName); - } catch (Exception e) { - generateSchemaforFieldsandProperties(xmlSchema, - sequence, - property.getPropertyType(), - propertyName, - property.getPropertyType().isArray()); + if(Map.class.isAssignableFrom((Class)((ParameterizedType)aType).getRawType())){ + generateWrappedSchemaTypeForMap(sequence, aType, propertyName); + } else { + try { + generateSchemaforGenericFields(xmlSchema, + sequence, + fieldArgTypes[0], + propertyName); + } catch (Exception e) { + generateSchemaforFieldsandProperties(xmlSchema, + sequence, + property.getPropertyType(), + propertyName, + property.getPropertyType().isArray()); + } + } + } else { - generateSchemaforFieldsandProperties(xmlSchema, - sequence, - property.getPropertyType(), - propertyName, - property.getPropertyType().isArray()); + if(genericFieldType != null && Map.class.isAssignableFrom((Class)genericFieldType)){ + generateWrappedSchemaTypeForMap(sequence, genericFieldType, propertyName); + } else { + generateSchemaforFieldsandProperties(xmlSchema, + sequence, + property.getPropertyType(), + propertyName, + property.getPropertyType().isArray()); + } } } } @@ -1665,4 +1692,152 @@ public class DefaultSchemaGenerator impl } } } + + /** + * Generate wrapped schema type for map. + * + * @param sequence the sequence + * @param genericParameterType the generic parameter type + * @param parameterName the parameter name + * @throws Exception the exception + */ + private void generateWrappedSchemaTypeForMap(XmlSchemaSequence sequence, + Type genericParameterType, String parameterName) throws Exception { + generateSchemaTypeForMap(sequence, genericParameterType, parameterName); + } + + /** + * Generate schema type for map. + * + * @param sequence the sequence + * @param genericParameterType the generic parameter type + * @param parameterName the parameter name + * @return the q name + * @throws Exception the exception + */ + protected QName generateSchemaTypeForMap(XmlSchemaSequence sequence, + Type genericParameterType, String parameterName) throws Exception { + /* + * In Doc/Lit Wrapped - sequence should not be null. + * In Doc/lit Bare - sequence should be null. + */ + Type keyType = Object.class; + Type valueType = Object.class; + String entryName = generateUniqueNameForMapEntry(); + String mapName = generateUniqueNameForMap(); + + if (genericParameterType instanceof ParameterizedType) { + ParameterizedType aType = (ParameterizedType) genericParameterType; + Type[] parameterArgTypes = aType.getActualTypeArguments(); + keyType = parameterArgTypes[0]; + valueType = parameterArgTypes[1]; + } + + XmlSchema xmlSchema = getXmlSchema(Constants.AXIS2_MAP_NAMESPACE_URI); + String targetNamespacePrefix = targetNamespacePrefixMap + .get(Constants.AXIS2_MAP_NAMESPACE_URI); + + XmlSchemaComplexType entryType = new XmlSchemaComplexType(xmlSchema); + QName entryTypeName = new QName(Constants.AXIS2_MAP_NAMESPACE_URI, + entryName, targetNamespacePrefix); + XmlSchemaSequence entrySequence = new XmlSchemaSequence(); + generateSchemaTypeForMapParameter(entrySequence, keyType, + Constants.MAP_KEY_ELEMENT_NAME); + generateSchemaTypeForMapParameter(entrySequence, valueType, + Constants.MAP_VALUE_ELEMENT_NAME); + entryType.setParticle(entrySequence); + entryType.setName(entryName); + xmlSchema.getItems().add(entryType); + + XmlSchemaElement entryElement = new XmlSchemaElement(); + entryElement.setName(Constants.MAP_ENTRY_ELEMENT_NAME); + entryElement.setNillable(true); + entryElement.setSchemaTypeName(entryTypeName); + entryElement.setMaxOccurs(Long.MAX_VALUE); + entryElement.setQName(entryTypeName); + + XmlSchemaComplexType mapType = new XmlSchemaComplexType(xmlSchema); + QName mapTypeName = new QName(Constants.AXIS2_MAP_NAMESPACE_URI, + mapName, targetNamespacePrefix); + XmlSchemaSequence mapSequence = new XmlSchemaSequence(); + mapSequence.getItems().add(entryElement); + mapType.setParticle(mapSequence); + mapType.setName(mapName); + xmlSchema.getItems().add(mapType); + + QName schemaTypeName = new QName(Constants.AXIS2_MAP_NAMESPACE_URI, + mapName); + addImport(getXmlSchema(schemaTargetNameSpace), schemaTypeName); + + if (sequence != null) { + XmlSchemaComplexType parameterType = new XmlSchemaComplexType( + xmlSchema); + QName parameterTypeName = new QName( + Constants.AXIS2_MAP_NAMESPACE_URI, mapName, + targetNamespacePrefix); + XmlSchemaSequence parameterSequence = new XmlSchemaSequence(); + parameterSequence.getItems().add(entryElement); + parameterType.setParticle(parameterSequence); + + XmlSchemaElement parameterElement = new XmlSchemaElement(); + parameterElement.setName(parameterName); + sequence.getItems().add(parameterElement); + parameterElement.setSchemaTypeName(parameterTypeName); + return parameterTypeName; + } + return mapTypeName; + } + + /** + * Generate schema type for map parameter. + * + * @param entrySequence the entry sequence + * @param parameterType the parameter type + * @param elementName the element name + * @throws Exception the exception + */ + private void generateSchemaTypeForMapParameter( + XmlSchemaSequence entrySequence, Type parameterType, + String elementName) throws Exception { + if (parameterType instanceof ParameterizedType) { + if (Map.class + .isAssignableFrom((Class) ((ParameterizedType) parameterType) + .getRawType())) { + generateWrappedSchemaTypeForMap(entrySequence, parameterType, + elementName); + + } else if (Collection.class + .isAssignableFrom((Class) ((ParameterizedType) parameterType) + .getRawType())) { + // TODO - support for Collection and Arrays + } else { + // TODO - support for custom ParameterizedTypes + } + } else { + generateSchemaForType(entrySequence, parameterType, elementName, + false); + } + } + + /** + * Provides unique name for a Map. + * + * @return the string + */ + private static String generateUniqueNameForMap() { + String name = Constants.MAP_MAP_ELEMENT_NAME + mapCount; + mapCount++; + return name; + } + + /** + * Provides unique name for a Map entry. + * + * @return the unique name for map entry + */ + private static String generateUniqueNameForMapEntry() { + String name = Constants.MAP_ENTRY_ELEMENT_NAME + entryCount; + entryCount++; + return name; + } } \ No newline at end of file Modified: axis/axis2/java/core/trunk/modules/kernel/src/org/apache/axis2/description/java2wsdl/DocLitBareSchemaGenerator.java URL: http://svn.apache.org/viewvc/axis/axis2/java/core/trunk/modules/kernel/src/org/apache/axis2/description/java2wsdl/DocLitBareSchemaGenerator.java?rev=1142991&r1=1142990&r2=1142991&view=diff ============================================================================== --- axis/axis2/java/core/trunk/modules/kernel/src/org/apache/axis2/description/java2wsdl/DocLitBareSchemaGenerator.java (original) +++ axis/axis2/java/core/trunk/modules/kernel/src/org/apache/axis2/description/java2wsdl/DocLitBareSchemaGenerator.java Tue Jul 5 11:25:06 2011 @@ -41,10 +41,12 @@ import javax.xml.namespace.QName; import java.lang.annotation.Annotation; import java.lang.reflect.Method; import java.lang.reflect.Modifier; +import java.lang.reflect.Type; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.LinkedHashMap; +import java.util.Map; public class DocLitBareSchemaGenerator extends DefaultSchemaGenerator { @@ -122,6 +124,7 @@ public class DocLitBareSchemaGenerator e uniqueMethods.put(methodName, jMethod); Class<?>[] paras = jMethod.getParameterTypes(); + Type[] genericParameterTypes = jMethod.getGenericParameterTypes(); String parameterNames[] = methodTable.getParameterNames(methodName); AxisMessage inMessage = axisOperation.getMessage(WSDLConstants.MESSAGE_LABEL_IN_VALUE); if (inMessage != null) { @@ -139,7 +142,7 @@ public class DocLitBareSchemaGenerator e for (int j = 0; j < paras.length; j++) { Class<?> methodParameter = paras[j]; String parameterName = getParameterName(parameterAnnotation, j, parameterNames); - if (generateRequestSchema(methodParameter , parameterName,jMethod, sequence)) { + if (generateRequestSchema(methodParameter , parameterName,jMethod, sequence, genericParameterTypes[j])) { break; } } @@ -155,7 +158,7 @@ public class DocLitBareSchemaGenerator e axisOperation); inMessage.setPartName(methodName); String parameterName = getParameterName(parameterAnnotation, 0, parameterNames); - if (generateRequestSchema(methodParameter , parameterName,jMethod, sequence)) { + if (generateRequestSchema(methodParameter , parameterName,jMethod, sequence, genericParameterTypes[0])) { break; } } else { @@ -168,7 +171,11 @@ public class DocLitBareSchemaGenerator e jMethod.getName() + " ]which have the same parameter names"); } else { processedParameters.put(parameterName, jMethod); - generateSchemaForType(null, methodParameter, parameterName); + if (methodParameter != null && Map.class.isAssignableFrom(methodParameter)){ + generateBareSchemaTypeForMap(parameterName, genericParameterTypes[0], null); + } else { + generateSchemaForType(null, methodParameter, parameterName); + } inMessage.setElementQName(typeTable.getQNamefortheType(parameterName)); inMessage.setPartName(parameterName); inMessage.setWrapped(false); @@ -180,6 +187,7 @@ public class DocLitBareSchemaGenerator e // for its return type Class<?> returnType = jMethod.getReturnType(); + Type genericReturnType = jMethod.getGenericReturnType(); if (!"void".equals(jMethod.getReturnType().getName())) { AxisMessage outMessage = axisOperation.getMessage( @@ -203,7 +211,11 @@ public class DocLitBareSchemaGenerator e generateSchemaForType(sequence, returnType, returnName); } } else { - generateSchemaForType(null, returnType, methodName + RESULT); + if (returnType != null && Map.class.isAssignableFrom(returnType)){ + generateBareSchemaTypeForMap(methodName + RESULT, genericReturnType, null); + } else { + generateSchemaForType(null, returnType, methodName + RESULT); + } outMessage.setWrapped(false); } outMessage.setElementQName(typeTable.getQNamefortheType(methodName + RESULT)); @@ -224,10 +236,12 @@ public class DocLitBareSchemaGenerator e private boolean generateRequestSchema(Class<?> methodParameter, String parameterName, Method jMethod, - XmlSchemaSequence sequence) throws Exception { + XmlSchemaSequence sequence, Type genericParameterType) throws Exception { if (nonRpcMethods.contains(jMethod.getName())) { generateSchemaForType(sequence, null, jMethod.getName()); return true; + } else if (methodParameter != null && Map.class.isAssignableFrom(methodParameter)){ + generateBareSchemaTypeForMap(parameterName, genericParameterType, sequence); } else { generateSchemaForType(sequence, methodParameter, parameterName); } @@ -359,5 +373,35 @@ public class DocLitBareSchemaGenerator e } return xmlSchema; } + + /** + * Generate bare schema type for map. + * + * @param paraName the para name + * @param genericParameterType the generic parameter type + * @param sequence the sequence + * @throws Exception the exception + */ + private void generateBareSchemaTypeForMap(String paraName, + Type genericParameterType, XmlSchemaSequence sequence) + throws Exception { + QName schemaTypeName = generateSchemaTypeForMap(sequence, + genericParameterType, paraName); + if (sequence != null) { + return; + } + XmlSchemaElement elt1 = new XmlSchemaElement(); + elt1.setSchemaTypeName(schemaTypeName); + elt1.setName(paraName); + elt1.setNillable(true); + QName elementName = new QName(schemaTargetNameSpace, paraName, + schema_namespace_prefix); + elt1.setQName(elementName); + XmlSchema xmlSchema = getXmlSchema(schemaTargetNameSpace); + xmlSchema.getElements().add(elementName, elt1); + xmlSchema.getItems().add(elt1); + typeTable.addComplexSchema(paraName, elementName); + + } } Modified: axis/axis2/java/core/trunk/modules/kernel/src/org/apache/axis2/description/java2wsdl/TypeTable.java URL: http://svn.apache.org/viewvc/axis/axis2/java/core/trunk/modules/kernel/src/org/apache/axis2/description/java2wsdl/TypeTable.java?rev=1142991&r1=1142990&r2=1142991&view=diff ============================================================================== --- axis/axis2/java/core/trunk/modules/kernel/src/org/apache/axis2/description/java2wsdl/TypeTable.java (original) +++ axis/axis2/java/core/trunk/modules/kernel/src/org/apache/axis2/description/java2wsdl/TypeTable.java Tue Jul 5 11:25:06 2011 @@ -29,7 +29,6 @@ import javax.xml.datatype.XMLGregorianCa import javax.xml.namespace.QName; import java.util.ArrayList; import java.util.HashMap; -import java.util.Hashtable; import java.util.List; import java.util.Map; import java.util.Vector; @@ -152,10 +151,6 @@ public class TypeTable { ANY_TYPE); simpleTypetoxsd.put(List.class.getName(), ANY_TYPE); - simpleTypetoxsd.put(HashMap.class.getName(), - ANY_TYPE); - simpleTypetoxsd.put(Hashtable.class.getName(), - ANY_TYPE); simpleTypetoxsd.put(Document.class.getName(), ANY_TYPE); //byteArrat simpleTypetoxsd.put("base64Binary", @@ -285,6 +280,20 @@ public class TypeTable { } return type; } + + /** + * Gets the schema type name. + * + * @param name the name + * @return the schema type name + */ + public QName getSchemaTypeName(String name) { + QName qName = getSimpleSchemaTypeName(name); + if( qName == null){ + qName = getComplexSchemaType(name); + } + return qName; + } }