/**
* 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.java5;
import java.lang.annotation.Annotation;
import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import javax.xml.bind.annotation.XmlEnumValue;
import org.apache.cxf.aegis.type.AegisType;
public class AnnotationReader {
private static final Class<? extends Annotation> WEB_PARAM = javax.jws.WebParam.class;
private static final Class<? extends Annotation> WEB_RESULT = javax.jws.WebResult.class;
private static final Class<? extends Annotation> XML_ATTRIBUTE =
javax.xml.bind.annotation.XmlAttribute.class;
private static final Class<? extends Annotation> XML_ELEMENT =
javax.xml.bind.annotation.XmlElement.class;
private static final Class<? extends Annotation> XML_SCHEMA =
javax.xml.bind.annotation.XmlSchema.class;
private static final Class<? extends Annotation> XML_TYPE =
javax.xml.bind.annotation.XmlType.class;
private static final Class<? extends Annotation> XML_TRANSIENT =
javax.xml.bind.annotation.XmlTransient.class;
public boolean isIgnored(AnnotatedElement element) {
return isAnnotationPresent(element,
IgnoreProperty.class,
XML_TRANSIENT);
}
public boolean isAttribute(AnnotatedElement element) {
return isAnnotationPresent(element,
XmlAttribute.class,
XML_ATTRIBUTE);
}
public boolean isElement(AnnotatedElement element) {
return isAnnotationPresent(element,
XmlElement.class,
XML_ELEMENT);
}
public Boolean isNillable(AnnotatedElement element) {
return Boolean.TRUE.equals(getAnnotationValue("nillable", // NOPMD
element,
Boolean.FALSE,
XmlElement.class,
XML_ELEMENT));
}
public static Boolean isNillable(Annotation[] anns) {
if (anns == null) {
return null;
}
return (Boolean)getAnnotationValue("nillable", // NOPMD
anns,
XmlElement.class,
XML_ELEMENT);
}
public Class<?> getType(AnnotatedElement element) {
Class<?> value = (Class<?>) getAnnotationValue("type",
element,
AegisType.class,
XmlAttribute.class,
XmlElement.class);
// jaxb uses a different default value
if (value == null) {
value = (Class<?>) getAnnotationValue("type",
element,
javax.xml.bind.annotation.XmlElement.DEFAULT.class,
XML_ELEMENT);
}
return value;
}
public Class<?> getParamType(Method method, int index) {
return (Class<?>) getAnnotationValue("type",
method,
index,
AegisType.class,
XmlParamType.class);
}
public Class<?> getReturnType(AnnotatedElement element) {
return (Class<?>) getAnnotationValue("type",
element,
AegisType.class,
XmlReturnType.class);
}
public String getName(AnnotatedElement element) {
String name = (String) getAnnotationValue("name",
element,
"",
XmlType.class,
XmlAttribute.class,
XmlElement.class);
// jaxb uses a different default value
if (name == null) {
name = (String) getAnnotationValue("name",
element,
"##default",
XML_TYPE,
XML_ATTRIBUTE,
XML_ELEMENT);
}
return name;
}
public String getParamTypeName(Method method, int index) {
return (String) getAnnotationValue("name",
method,
index,
AegisType.class,
XmlParamType.class);
}
public String getReturnTypeName(AnnotatedElement element) {
return (String) getAnnotationValue("name",
element,
"",
XmlReturnType.class);
}
public String getNamespace(AnnotatedElement element) {
// some poor class loader implementations may end not define Package elements
if (element == null) {
return null;
}
String namespace = (String) getAnnotationValue("namespace",
element,
"",
XmlType.class,
XmlAttribute.class,
XmlElement.class,
XML_SCHEMA);
// jaxb uses a different default value
if (namespace == null) {
namespace = (String) getAnnotationValue("namespace",
element,
"##default",
XML_TYPE,
XML_ATTRIBUTE,
XML_ELEMENT);
}
return namespace;
}
public String getParamNamespace(Method method, int index) {
String namespace = (String) getAnnotationValue("namespace",
method,
index,
"",
XmlParamType.class);
// JWS annotation field is named targetNamespace
if (namespace == null) {
namespace = (String) getAnnotationValue("targetNamespace", method, index, "", WEB_PARAM);
}
return namespace;
}
public String getReturnNamespace(AnnotatedElement element) {
String namespace = (String) getAnnotationValue("namespace",
element,
"",
XmlReturnType.class);
// JWS annotation field is named targetNamespace
if (namespace == null) {
namespace = (String) getAnnotationValue("targetNamespace", element, "", WEB_RESULT);
}
return namespace;
}
public int getMinOccurs(AnnotatedElement element) {
String minOccurs = (String) getAnnotationValue("minOccurs",
element,
"",
XmlElement.class);
if (minOccurs != null) {
return Integer.parseInt(minOccurs);
}
// check jaxb annotation
Boolean required = (Boolean) getAnnotationValue("required", element, null, XML_ELEMENT);
if (Boolean.TRUE.equals(required)) {
return 1;
}
return 0;
}
public static Integer getMinOccurs(Annotation[] anns) {
if (anns == null) {
return null;
}
String minOccurs = (String) getAnnotationValue("minOccurs",
anns,
XmlElement.class);
if (minOccurs != null) {
return Integer.valueOf(minOccurs);
}
// check jaxb annotation
Boolean required = (Boolean) getAnnotationValue("required", anns, XML_ELEMENT);
if (Boolean.TRUE.equals(required)) {
return 1;
}
return null;
}
public boolean isExtensibleElements(AnnotatedElement element, boolean defaultValue) {
Boolean extensibleElements = (Boolean) getAnnotationValue("extensibleElements",
element,
Boolean.TRUE,
XmlType.class);
if (extensibleElements == null) {
return defaultValue;
}
return extensibleElements;
}
public boolean isExtensibleAttributes(AnnotatedElement element, boolean defaultValue) {
Boolean extensibleAttributes = (Boolean) getAnnotationValue("extensibleAttributes",
element,
Boolean.TRUE,
XmlType.class);
if (extensibleAttributes == null) {
return defaultValue;
}
return extensibleAttributes;
}
@SafeVarargs
private static boolean isAnnotationPresent(AnnotatedElement element, // NOPMD
Class<? extends Annotation>... annotations) {
for (Class<?> annotation : annotations) {
if (annotation != null && element.isAnnotationPresent(annotation.asSubclass(Annotation.class))) {
return true;
}
}
return false;
}
@SafeVarargs
static Object getAnnotationValue(String name,
AnnotatedElement element,
Object ignoredValue,
Class<? extends Annotation>... annotations) {
for (Class<?> annotation : annotations) {
if (annotation != null && element != null) {
try {
Annotation ann = element.getAnnotation(annotation.asSubclass(Annotation.class));
if (ann != null) {
Method method = ann.getClass().getMethod(name);
Object value = method.invoke(ann);
if ((ignoredValue == null && value != null) || (ignoredValue != null
&& !ignoredValue.equals(value))) {
return value;
}
}
} catch (Exception ignored) {
// annotation did not have value
}
}
}
return null;
}
@SafeVarargs
static Object getAnnotationValue(String name,
Annotation[] anns,
Class<? extends Annotation>... annotations) {
for (Class<?> annotation : annotations) {
if (annotation != null) {
try {
for (Annotation ann : anns) {
if (annotation.isInstance(ann)) {
Method method = ann.getClass().getMethod(name);
return method.invoke(ann);
}
}
} catch (Exception ignored) {
// annotation did not have value
}
}
}
return null;
}
@SafeVarargs
static Object getAnnotationValue(String name,
Method method,
int index,
Object ignoredValue,
Class<? extends Annotation>... annotations) {
if (method.getParameterAnnotations() == null
|| method.getParameterAnnotations().length <= index
|| method.getParameterAnnotations()[index] == null) {
return null;
}
for (Class<? extends Annotation> annotation : annotations) {
if (annotation != null) {
try {
Annotation ann = getAnnotation(method, index, annotation);
if (ann != null) {
Object value = ann.getClass().getMethod(name).invoke(ann);
if ((ignoredValue == null && value != null) || (ignoredValue != null
&& !ignoredValue.equals(value))) {
return value;
}
}
} catch (Exception ignored) {
// annotation did not have value
}
}
}
return null;
}
private static Annotation getAnnotation(Method method, int index, Class<? extends Annotation> type) {
if (method.getParameterAnnotations() == null
|| method.getParameterAnnotations().length <= index
|| method.getParameterAnnotations()[index] == null) {
return null;
}
Annotation[] annotations = method.getParameterAnnotations()[index];
for (Annotation annotation : annotations) {
if (type.isInstance(annotation)) {
return annotation;
}
}
return null;
}
public boolean isFlat(Annotation[] annotations) {
if (annotations != null) {
for (Annotation a : annotations) {
if (a instanceof XmlFlattenedArray) {
return true;
}
}
}
return false;
}
public static String getEnumValue(Enum<?> enumConstant) {
@SuppressWarnings("rawtypes")
Class<? extends Enum> enumClass = enumConstant.getClass();
try {
Field constantField = enumClass.getDeclaredField(enumConstant.name());
XmlEnumValue constantValueAnnotation = constantField.getAnnotation(XmlEnumValue.class);
if (constantValueAnnotation == null) {
return null;
}
return constantValueAnnotation.value();
} catch (NoSuchFieldException e) {
return null;
}
}
}