blob: dc04fb3b622e633a741899b58c6231de61085017 [file] [log] [blame]
/*
* 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.axis2.jaxws.wrapper.impl;
import org.apache.axis2.jaxws.i18n.Messages;
import org.apache.axis2.jaxws.utility.PropertyDescriptorPlus;
import org.apache.axis2.jaxws.utility.XMLRootElementUtil;
import org.apache.axis2.jaxws.wrapper.JAXBWrapperTool;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* The JAXBWrapper tool is used to create a JAXB Object from a series of child objects (wrap) or get
* the child objects from a JAXB Object (unwrap)
*/
public class JAXBWrapperToolImpl implements JAXBWrapperTool {
private static final Log log = LogFactory.getLog(JAXBWrapperTool.class);
/**
* unwrap Returns the list of child objects of the jaxb object
*
* @param jaxbObject that represents the type
* @param childNames list of xml child names as String
* @param pdMap PropertyDescriptor map for this jaxbObject
* @return list of Objects in the same order as the element names.
*/
public Object[] unWrap(Object jaxbObject,
List<String> childNames,
Map<String, PropertyDescriptorPlus> pdMap) throws JAXBWrapperException {
if (jaxbObject == null) {
throw new JAXBWrapperException(Messages.getMessage("JAXBWrapperErr1"));
}
if (childNames == null) {
throw new JAXBWrapperException(Messages.getMessage("JAXBWrapperErr2"));
}
// Get the object that will have the property descriptors (i.e. the object representing the complexType)
Object jaxbComplexTypeObj = jaxbObject;
if (log.isDebugEnabled()) {
log.debug("Invoking unWrap() method with jaxb object:" +
jaxbComplexTypeObj.getClass().getName());
log.debug("The input child xmlnames are: " + toString(childNames));
}
// Check the PropertyDescriptorPlus map if debug is enabled.
// The method makes sure that each child name has a matching jaxb property
if (log.isDebugEnabled()) {
checkPropertyDescriptorMap(jaxbComplexTypeObj.getClass(), childNames, pdMap);
}
// Get the corresponsing objects from the jaxb bean
ArrayList<Object> objList = new ArrayList<Object>();
for (String childName : childNames) {
PropertyDescriptorPlus propInfo = pdMap.get(childName);
Object object = null;
if (propInfo == null) {
throw new JAXBWrapperException(
Messages.getMessage("JAXBWrapperErr6",
jaxbComplexTypeObj.getClass().getName(),
childName));
}
try {
object = propInfo.get(jaxbComplexTypeObj);
} catch (Throwable e) {
if (log.isDebugEnabled()) {
log.debug("An exception " + e.getClass() +
"occurred while trying to call get() on " + propInfo);
log.debug("The corresponding xml child name is: " + childName);
}
throw new JAXBWrapperException(e);
}
objList.add(object);
}
Object[] jaxbObjects = objList.toArray();
objList = null;
return jaxbObjects;
}
/**
* wrap Creates a jaxb object that is initialized with the child objects.
* <p/>
* Note that the jaxbClass must be the class the represents the complexType. (It should never be
* JAXBElement)
*
* @param jaxbClass
* @param childNames list of xml child names as String
* @param childObjects, component type objects
* @param pdMap PropertyDescriptor map for this jaxbObject
*/
public Object wrap(Class jaxbClass,
List<String> childNames,
Map<String, Object> childObjects,
Map<String, Class> declaredClassMap,
Map<String, PropertyDescriptorPlus> pdMap) throws JAXBWrapperException {
if (childNames == null || childObjects == null) {
throw new JAXBWrapperException(Messages.getMessage("JAXBWrapperErr3"));
}
if (childNames.size() != childObjects.size()) {
throw new JAXBWrapperException(Messages.getMessage("JAXBWrapperErr4"));
}
if (log.isDebugEnabled()) {
log.debug("Invoking unwrap() method to create jaxb object:" + jaxbClass.getName());
log.debug("The input child xmlnames are: " + toString(childNames));
}
// Just like unWrap, check the property descriptor map to make sure it is accurate
if (log.isDebugEnabled()) {
checkPropertyDescriptorMap(jaxbClass, childNames, pdMap);
}
// The jaxb object always has a default constructor. Create the object
Object jaxbObject = null;
try {
jaxbObject = jaxbClass.newInstance();
} catch (Throwable t) {
if (log.isDebugEnabled()) {
log.debug("An exception " + t.getClass() +
"occurred while trying to create jaxbobject " + jaxbClass.getName());
}
throw new JAXBWrapperException(t);
}
// Now set each object onto the jaxb object
for (String childName : childNames) {
PropertyDescriptorPlus propInfo = pdMap.get(childName);
Object value = childObjects.get(childName);
Class dclClass = declaredClassMap.get(childName);
if (propInfo == null) {
throw new JAXBWrapperException(Messages.getMessage("JAXBWrapperErr6",
jaxbClass.getName(),
childName));
}
try {
propInfo.set(jaxbObject, value, dclClass);
} catch (Throwable t) {
if (log.isDebugEnabled()) {
log.debug("An exception " + t.getClass() +
"occurred while trying to call set() on " + propInfo);
log.debug("The corresponding xml child name is: " + childName);
String name = (value == null) ? "<null>" : value.getClass().getName();
log.debug("The corresponding value object is: " + name);
}
throw new JAXBWrapperException(t);
}
}
// Return the jaxb object
return jaxbObject;
}
/**
* This code checks the pdMap to make sure that a PropertyDescriptor
* exists for each child name. This code should only be called when
* debug is enabled or an exception occurs. (It is too slow for the mainline path)
* @param jaxbClass
* @param xmlChildNames
* @param pdMap
* @throws JAXBWrapperException
*/
private void checkPropertyDescriptorMap(Class jaxbClass,
List<String> xmlChildNames,
Map<String, PropertyDescriptorPlus> pdMap)
throws JAXBWrapperException {
for (int i = 0; i < xmlChildNames.size(); i++) {
String xmlChildName = xmlChildNames.get(i);
PropertyDescriptorPlus pd = pdMap.get(xmlChildName);
if (pd == null) {
// Each xml child name must have a matching property.
if (log.isDebugEnabled()) {
log.debug(
"Error occurred trying to match an xml name to a child of a jaxb object");
log.debug(" The JAXBClass is:" + jaxbClass.getName());
log.debug(" The child name that we are looking for is:" + xmlChildName);
log.debug(" The JAXBClass has the following child xml names:" +
toString(pdMap.keySet()));
log.debug(" Complete list of child names that we are looking for:" +
toString(xmlChildNames));
}
throw new JAXBWrapperException(
Messages.getMessage("JAXBWrapperErr6", jaxbClass.getName(), xmlChildName));
}
}
}
/**
* @param collection
* @return list of the names in the collection
*/
private String toString(Collection<String> collection) {
String text = "[";
if (collection == null) {
return "[]";
}
boolean first = true;
for (String name : collection) {
if (first) {
first = false;
text += name;
} else {
text += "," + name;
}
}
return text + "]";
}
public Object[] unWrap(Object jaxbObject, List<String> childNames) throws JAXBWrapperException {
// Get the property descriptor map for this JAXBClass
Class jaxbClass = jaxbObject.getClass();
Map<String, PropertyDescriptorPlus> pdMap = null;
try {
pdMap = XMLRootElementUtil.createPropertyDescriptorMap(jaxbClass);
} catch (Throwable t) {
log.debug("Error occurred to build the PropertyDescriptor map");
log.debug(" The JAXBClass is:" + jaxbClass.getName());
throw new JAXBWrapperException(t);
}
// Delegate
return unWrap(jaxbObject, childNames, pdMap);
}
public Object wrap(Class jaxbClass, List<String> childNames, Map<String, Object> childObjects)
throws JAXBWrapperException {
// Get the property descriptor map
Map<String, PropertyDescriptorPlus> pdMap = null;
try {
pdMap = XMLRootElementUtil.createPropertyDescriptorMap(jaxbClass);
} catch (Throwable t) {
log.debug("Error occurred to build the PropertyDescriptor map");
log.debug(" The JAXBClass is:" + jaxbClass.getName());
throw new JAXBWrapperException(t);
}
HashMap<String, Class> declaringClass = new HashMap<String, Class>();
// Delegate
return wrap(jaxbClass, childNames, childObjects, declaringClass, pdMap);
}
}