001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one
003: * or more contributor license agreements. See the NOTICE file
004: * distributed with this work for additional information
005: * regarding copyright ownership. The ASF licenses this file
006: * to you under the Apache License, Version 2.0 (the
007: * "License"); you may not use this file except in compliance
008: * with the License. You may obtain a copy of the License at
009: *
010: * http://www.apache.org/licenses/LICENSE-2.0
011: *
012: * Unless required by applicable law or agreed to in writing,
013: * software distributed under the License is distributed on an
014: * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015: * KIND, either express or implied. See the License for the
016: * specific language governing permissions and limitations
017: * under the License.
018: */
019:
020: package org.apache.axis2.jaxws.wrapper.impl;
021:
022: import org.apache.axis2.jaxws.i18n.Messages;
023: import org.apache.axis2.jaxws.utility.PropertyDescriptorPlus;
024: import org.apache.axis2.jaxws.utility.XMLRootElementUtil;
025: import org.apache.axis2.jaxws.wrapper.JAXBWrapperTool;
026: import org.apache.commons.logging.Log;
027: import org.apache.commons.logging.LogFactory;
028:
029: import java.util.ArrayList;
030: import java.util.Collection;
031: import java.util.HashMap;
032: import java.util.List;
033: import java.util.Map;
034:
035: /**
036: * The JAXBWrapper tool is used to create a JAXB Object from a series of child objects (wrap) or get
037: * the child objects from a JAXB Object (unwrap)
038: */
039: public class JAXBWrapperToolImpl implements JAXBWrapperTool {
040:
041: private static final Log log = LogFactory
042: .getLog(JAXBWrapperTool.class);
043:
044: /**
045: * unwrap Returns the list of child objects of the jaxb object
046: *
047: * @param jaxbObject that represents the type
048: * @param childNames list of xml child names as String
049: * @param pdMap PropertyDescriptor map for this jaxbObject
050: * @return list of Objects in the same order as the element names.
051: */
052: public Object[] unWrap(Object jaxbObject, List<String> childNames,
053: Map<String, PropertyDescriptorPlus> pdMap)
054: throws JAXBWrapperException {
055:
056: if (jaxbObject == null) {
057: throw new JAXBWrapperException(Messages
058: .getMessage("JAXBWrapperErr1"));
059: }
060: if (childNames == null) {
061: throw new JAXBWrapperException(Messages
062: .getMessage("JAXBWrapperErr2"));
063: }
064:
065: // Get the object that will have the property descriptors (i.e. the object representing the complexType)
066: Object jaxbComplexTypeObj = jaxbObject;
067:
068: if (log.isDebugEnabled()) {
069: log.debug("Invoking unWrap() method with jaxb object:"
070: + jaxbComplexTypeObj.getClass().getName());
071: log.debug("The input child xmlnames are: "
072: + toString(childNames));
073: }
074: // Get the PropertyDescriptorPlus map.
075: // The method makes sure that each child name has a matching jaxb property
076: checkPropertyDescriptorMap(jaxbComplexTypeObj.getClass(),
077: childNames, pdMap);
078:
079: // Get the corresponsing objects from the jaxb bean
080: ArrayList<Object> objList = new ArrayList<Object>();
081: for (String childName : childNames) {
082: PropertyDescriptorPlus propInfo = pdMap.get(childName);
083: Object object = null;
084: try {
085: object = propInfo.get(jaxbComplexTypeObj);
086: } catch (Throwable e) {
087: if (log.isDebugEnabled()) {
088: log.debug("An exception " + e.getClass()
089: + "occurred while trying to call get() on "
090: + propInfo);
091: log.debug("The corresponding xml child name is: "
092: + childName);
093: }
094: throw new JAXBWrapperException(e);
095: }
096: objList.add(object);
097: }
098: Object[] jaxbObjects = objList.toArray();
099: objList = null;
100: return jaxbObjects;
101:
102: }
103:
104: /**
105: * wrap Creates a jaxb object that is initialized with the child objects.
106: * <p/>
107: * Note that the jaxbClass must be the class the represents the complexType. (It should never be
108: * JAXBElement)
109: *
110: * @param jaxbClass
111: * @param childNames list of xml child names as String
112: * @param childObjects, component type objects
113: * @param pdMap PropertyDescriptor map for this jaxbObject
114: */
115: public Object wrap(Class jaxbClass, List<String> childNames,
116: Map<String, Object> childObjects,
117: Map<String, PropertyDescriptorPlus> pdMap)
118: throws JAXBWrapperException {
119:
120: if (childNames == null || childObjects == null) {
121: throw new JAXBWrapperException(Messages
122: .getMessage("JAXBWrapperErr3"));
123: }
124: if (childNames.size() != childObjects.size()) {
125: throw new JAXBWrapperException(Messages
126: .getMessage("JAXBWrapperErr4"));
127: }
128:
129: if (log.isDebugEnabled()) {
130: log.debug("Invoking unwrap() method to create jaxb object:"
131: + jaxbClass.getName());
132: log.debug("The input child xmlnames are: "
133: + toString(childNames));
134: }
135:
136: // Just like unWrap, get the property info map
137: checkPropertyDescriptorMap(jaxbClass, childNames, pdMap);
138:
139: // The jaxb object always has a default constructor. Create the object
140: Object jaxbObject = null;
141: try {
142: jaxbObject = jaxbClass.newInstance();
143: } catch (Throwable t) {
144: if (log.isDebugEnabled()) {
145: log
146: .debug("An exception "
147: + t.getClass()
148: + "occurred while trying to create jaxbobject "
149: + jaxbClass.getName());
150: }
151: throw new JAXBWrapperException(t);
152: }
153:
154: // Now set each object onto the jaxb object
155: for (String childName : childNames) {
156: PropertyDescriptorPlus propInfo = pdMap.get(childName);
157: Object value = childObjects.get(childName);
158: try {
159: propInfo.set(jaxbObject, value);
160: } catch (Throwable t) {
161:
162: if (log.isDebugEnabled()) {
163: log
164: .debug("An exception "
165: + t.getClass()
166: + "occurred while trying to call set() on "
167: + propInfo);
168: log.debug("The corresponding xml child name is: "
169: + childName);
170: String name = (value == null) ? "<null>" : value
171: .getClass().getName();
172: log.debug("The corresponding value object is: "
173: + name);
174: }
175: throw new JAXBWrapperException(t);
176: }
177: }
178:
179: // Return the jaxb object
180: return jaxbObject;
181: }
182:
183: /** Makes sure that each xmlChildName is present in the odMap */
184: private void checkPropertyDescriptorMap(Class jaxbClass,
185: List<String> xmlChildNames,
186: Map<String, PropertyDescriptorPlus> pdMap)
187: throws JAXBWrapperException {
188: // The following code is slow, and doc/lit wrapped is in the main
189: // performance flow. So only do this check if debug is enabled.
190: if (log.isDebugEnabled()) {
191: for (int i = 0; i < xmlChildNames.size(); i++) {
192: String xmlChildName = xmlChildNames.get(i);
193: PropertyDescriptorPlus pd = pdMap.get(xmlChildName);
194: if (pd == null) {
195: // Each xml child name must have a matching property.
196:
197: log
198: .debug("Error occurred trying to match an xml name to a child of a jaxb object");
199: log.debug(" The JAXBClass is:"
200: + jaxbClass.getName());
201: log
202: .debug(" The child name that we are looking for is:"
203: + xmlChildName);
204: log
205: .debug(" The JAXBClass has the following child xml names:"
206: + toString(pdMap.keySet()));
207: log
208: .debug(" Complete list of child names that we are looking for:"
209: + toString(xmlChildNames));
210:
211: throw new JAXBWrapperException(Messages.getMessage(
212: "JAXBWrapperErr6", jaxbClass.getName(),
213: xmlChildName));
214: }
215: }
216: }
217: }
218:
219: /**
220: * @param collection
221: * @return list of the names in the collection
222: */
223: private String toString(Collection<String> collection) {
224: String text = "[";
225: if (collection == null) {
226: return "[]";
227: }
228: boolean first = true;
229: for (String name : collection) {
230: if (first) {
231: first = false;
232: text += name;
233: } else {
234: text += "," + name;
235: }
236: }
237: return text + "]";
238: }
239:
240: public Object[] unWrap(Object jaxbObject, List<String> childNames)
241: throws JAXBWrapperException {
242: // Get the property descriptor map for this JAXBClass
243: Class jaxbClass = jaxbObject.getClass();
244: Map<String, PropertyDescriptorPlus> pdMap = null;
245: try {
246: pdMap = XMLRootElementUtil
247: .createPropertyDescriptorMap(jaxbClass);
248: } catch (Throwable t) {
249: log
250: .debug("Error occurred to build the PropertyDescriptor map");
251: log.debug(" The JAXBClass is:" + jaxbClass.getName());
252: throw new JAXBWrapperException(t);
253: }
254:
255: // Delegate
256: return unWrap(jaxbObject, childNames, pdMap);
257: }
258:
259: public Object wrap(Class jaxbClass, List<String> childNames,
260: Map<String, Object> childObjects)
261: throws JAXBWrapperException {
262: // Get the property descriptor map
263: Map<String, PropertyDescriptorPlus> pdMap = null;
264: try {
265: pdMap = XMLRootElementUtil
266: .createPropertyDescriptorMap(jaxbClass);
267: } catch (Throwable t) {
268: log
269: .debug("Error occurred to build the PropertyDescriptor map");
270: log.debug(" The JAXBClass is:" + jaxbClass.getName());
271: throw new JAXBWrapperException(t);
272: }
273:
274: // Delegate
275: return wrap(jaxbClass, childNames, childObjects, pdMap);
276: }
277:
278: }
|