/**
* 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.jaxb;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.List;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.annotation.XmlElement;
public final class WrapperHelper {
private WrapperHelper() {
// complete
}
public static void setWrappedPart(String partName, Object wrapperType, Object part)
throws IllegalAccessException, NoSuchMethodException, InvocationTargetException {
if (part instanceof List) {
setWrappedListProperty(partName, wrapperType, part);
} else {
String fieldName = partName;
if (JAXBUtils.isJavaKeyword(partName)) {
fieldName = JAXBUtils.nameToIdentifier(partName, JAXBUtils.IdentifierType.VARIABLE);
}
if (part == null) {
XmlElement el = null;
Field elField = null;
for (Field field : wrapperType.getClass().getDeclaredFields()) {
if (field.getName().equals(fieldName)) {
elField = field;
el = elField.getAnnotation(XmlElement.class);
break;
}
}
if (el != null
&& !el.nillable()
&& elField.getType().isPrimitive()) {
throw new IllegalArgumentException("null value for field not permitted.");
}
return;
}
String modifier = JAXBUtils.nameToIdentifier(partName, JAXBUtils.IdentifierType.SETTER);
String modifier2 = modifier;
if ("return".equals(partName)) {
//some versions of jaxb map "return" to "set_return" instead of "setReturn"
modifier2 = "set_return";
}
boolean setInvoked = false;
for (Method method : wrapperType.getClass().getMethods()) {
if (method.getParameterTypes() != null && method.getParameterTypes().length == 1
&& (modifier.equals(method.getName())
|| modifier2.equals(method.getName()))) {
if ("javax.xml.bind.JAXBElement".equals(method.getParameterTypes()[0].getName())) {
if (!setJAXBElementValueIntoWrapType(method, wrapperType, part)) {
throw new RuntimeException("Failed to set the part value (" + part
+ ") to wrapper type (" + wrapperType.getClass() + ")");
}
} else {
method.invoke(wrapperType, part);
}
setInvoked = true;
break;
}
}
if (!setInvoked) {
Field elField = getField(wrapperType, partName, fieldName);
// JAXB Type get XmlElement Annotation
if (elField != null) {
elField.setAccessible(true);
elField.set(wrapperType, part);
setInvoked = true;
}
}
if (!setInvoked) {
throw new IllegalArgumentException("Could not find a modifier method on Wrapper Type for "
+ partName);
}
}
}
private static Field getField(Object wrapperType, String partName, String fieldName) {
// match fieldName and partName first
for (Field field : wrapperType.getClass().getDeclaredFields()) {
if (field.getName().equals(fieldName)) {
XmlElement el = field.getAnnotation(XmlElement.class);
if (el != null && el.name().equals(partName)) {
return field;
}
}
}
// if above fails, check partName only
for (Field field : wrapperType.getClass().getDeclaredFields()) {
XmlElement el = field.getAnnotation(XmlElement.class);
if (el != null && el.name().equals(partName)) {
return field;
}
}
return null;
}
private static boolean setJAXBElementValueIntoWrapType(Method method, Object wrapType, Object value) {
String typeClassName = wrapType.getClass().getCanonicalName();
String objectFactoryClassName = typeClassName.substring(0, typeClassName.lastIndexOf('.'))
+ ".ObjectFactory";
try {
Object objectFactory = wrapType.getClass().getClassLoader().loadClass(objectFactoryClassName)
.newInstance();
String methodName = "create" + wrapType.getClass().getSimpleName()
+ method.getName().substring(3);
Method objectFactoryMethod = objectFactory.getClass().getMethod(methodName, value.getClass());
if (objectFactoryMethod != null) {
JAXBElement je = (JAXBElement)objectFactoryMethod.invoke(objectFactory, value);
method.invoke(wrapType, je);
} else {
return false;
}
return true;
} catch (Exception e) {
return false;
}
}
private static void setWrappedListProperty(String partName, Object wrapperType, Object part)
throws IllegalAccessException, NoSuchMethodException, InvocationTargetException {
String accessorName = JAXBUtils.nameToIdentifier(partName, JAXBUtils.IdentifierType.GETTER);
for (Method method : wrapperType.getClass().getMethods()) {
if (accessorName.equals(method.getName())
&& List.class.isAssignableFrom(method.getReturnType())) {
Object ret = method.invoke(wrapperType);
Method addAll = ret.getClass().getMethod("addAll", Collection.class);
addAll.invoke(ret, part);
break;
}
}
}
public static Object getWrappedPart(String partName, Object wrapperType, Class<?> partClazz)
throws IllegalAccessException, NoSuchMethodException, InvocationTargetException {
String accessor = JAXBUtils.nameToIdentifier(partName, JAXBUtils.IdentifierType.GETTER);
if (partClazz.equals(boolean.class) || partClazz.equals(Boolean.class)) {
// JAXB Exception to get the Boolean property
accessor = accessor.replaceFirst("get", "is");
}
for (Method method : wrapperType.getClass().getMethods()) {
if (method.getParameterTypes().length == 0 && accessor.equals(method.getName())) {
return getValue(method, wrapperType);
}
}
return null;
}
public static Object getWrappedPart(String partName, Object wrapperType, String elementType)
throws IllegalAccessException, NoSuchMethodException, InvocationTargetException {
String accessor = JAXBUtils.nameToIdentifier(partName, JAXBUtils.IdentifierType.GETTER);
Method method = null;
NoSuchMethodException nsex = null;
try {
method = wrapperType.getClass().getMethod(accessor, new Class[0]);
} catch (NoSuchMethodException ex) {
//ignore for now
nsex = (NoSuchMethodException)ex.fillInStackTrace();
}
Field elField = null;
if (method == null
&& elementType != null
&& "boolean".equals(elementType.toLowerCase())) {
elField = getElField(partName, wrapperType);
if (elField == null
|| (!Collection.class.isAssignableFrom(elField.getType())
&& !elField.getType().isArray())) {
try {
method = wrapperType.getClass().getMethod(accessor.replaceFirst("get", "is"),
new Class[0]);
} catch (NoSuchMethodException ex) {
//ignore for now
}
}
}
if (method == null
&& "return".equals(partName)) {
//RI generated code uses this
try {
method = wrapperType.getClass().getMethod("get_return", new Class[0]);
} catch (NoSuchMethodException ex) {
try {
method = wrapperType.getClass().getMethod("is_return",
new Class[0]);
} catch (NoSuchMethodException ex2) {
//ignore for now
}
}
}
if (method != null) {
return getValue(method, wrapperType);
}
if (elField == null) {
elField = getElField(partName, wrapperType);
}
if (elField != null) {
// JAXB Type get XmlElement Annotation
XmlElement el = elField.getAnnotation(XmlElement.class);
if (el != null
&& partName.equals(el.name())) {
elField.setAccessible(true);
return elField.get(wrapperType);
}
} else if (nsex != null) {
throw nsex;
}
return null;
}
private static Field getElField(String partName, Object wrapperType) {
String fieldName = JAXBUtils.nameToIdentifier(partName, JAXBUtils.IdentifierType.VARIABLE);
Field elField = null;
for (Field field : wrapperType.getClass().getDeclaredFields()) {
if (field.getName().equals(fieldName)) {
elField = field;
break;
}
}
return elField;
}
public static Object getWrappedPart(String partName, Object wrapperType) throws IllegalAccessException,
NoSuchMethodException, InvocationTargetException {
String accessor = JAXBUtils.nameToIdentifier(partName, JAXBUtils.IdentifierType.GETTER);
// TODO: There must be a way to determine the class by inspecting
// wrapperType
// if (partClazz.equals(boolean.class) ||
// partClazz.equals(Boolean.class)) {
// //JAXB Exception to get the Boolean property
// accessor = accessor.replaceFirst("get", "is");
// }
for (Method method : wrapperType.getClass().getMethods()) {
if (method.getParameterTypes().length == 0 && accessor.equals(method.getName())) {
return getValue(method, wrapperType);
}
}
return null;
}
private static Object getValue(Method method, Object in) throws IllegalAccessException,
InvocationTargetException {
if ("javax.xml.bind.JAXBElement".equals(method.getReturnType().getCanonicalName())) {
JAXBElement je = (JAXBElement)method.invoke(in);
return je == null ? je : je.getValue();
} else {
return method.invoke(in);
}
}
}