/* * Copyright 2011, 2012 Odysseus Software GmbH * * Licensed 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.synapse.commons.staxon.core.json.jaxb; import java.lang.reflect.Method; import javax.xml.XMLConstants; import javax.xml.bind.JAXBElement; import javax.xml.bind.JAXBException; import javax.xml.bind.annotation.XmlElementDecl; import javax.xml.bind.annotation.XmlNs; import javax.xml.bind.annotation.XmlRegistry; import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlSchema; import javax.xml.bind.annotation.XmlType; import javax.xml.namespace.QName; /** * Root name/element provider. */ public class JsonXMLRootProvider { protected String getNamespaceURI(XmlType xmlType, XmlSchema xmlSchema) { if ("##default".equals(xmlType.namespace())) { return xmlSchema == null ? XMLConstants.NULL_NS_URI : xmlSchema.namespace(); } else { return xmlType.namespace(); } } protected String getNamespaceURI(XmlRootElement xmlRootElement, XmlSchema xmlSchema) { if ("##default".equals(xmlRootElement.namespace())) { return xmlSchema == null ? XMLConstants.NULL_NS_URI : xmlSchema.namespace(); } else { return xmlRootElement.namespace(); } } protected String getNamespaceURI(XmlElementDecl xmlElementDecl, XmlSchema xmlSchema) { if ("##default".equals(xmlElementDecl.namespace())) { return xmlSchema == null ? XMLConstants.NULL_NS_URI : xmlSchema.namespace(); } else { return xmlElementDecl.namespace(); } } protected String getPrefix(String namespaceURI, XmlSchema xmlSchema) { if (xmlSchema != null) { for (XmlNs xmlns : xmlSchema.xmlns()) { if (xmlns.namespaceURI().equals(namespaceURI)) { return xmlns.prefix(); } } } return XMLConstants.DEFAULT_NS_PREFIX; } /** * Calculate root element name for an <code>@XmlRootElement</code>-annotated type. * * @param type * @return element name */ protected QName getXmlRootElementName(Class<?> type) { XmlRootElement xmlRootElement = type.getAnnotation(XmlRootElement.class); if (xmlRootElement == null) { return null; } String localName; if ("##default".equals(xmlRootElement.name())) { localName = Character.toLowerCase(type.getSimpleName().charAt(0)) + type.getSimpleName().substring(1); } else { localName = xmlRootElement.name(); } XmlSchema xmlSchema = type.getPackage().getAnnotation(XmlSchema.class); String namespaceURI = getNamespaceURI(xmlRootElement, xmlSchema); return new QName(namespaceURI, localName, getPrefix(namespaceURI, xmlSchema)); } /** * Calculate root element name for an <code>@XmlType</code>-annotated type. * * @param type * @return element name */ protected QName getXmlTypeName(Class<?> type) { Method method = getXmlElementDeclMethod(type); if (method == null) { return null; } XmlElementDecl xmlElementDecl = method.getAnnotation(XmlElementDecl.class); if (xmlElementDecl == null) { return null; } XmlSchema xmlSchema = type.getPackage().getAnnotation(XmlSchema.class); String namespaceURI = getNamespaceURI(xmlElementDecl, xmlSchema); return new QName(namespaceURI, xmlElementDecl.name(), getPrefix(namespaceURI, xmlSchema)); } /** * Determine <code>@XmlElementDecl</code>-annotated factory method to create {@link JAXBElement} * for an <code>@XmlType</code>-annotated type * * @param type * @return element */ protected Method getXmlElementDeclMethod(Class<?> type) { XmlType xmlType = type.getAnnotation(XmlType.class); if (xmlType == null) { return null; } Class<?> factoryClass = xmlType.factoryClass(); if (factoryClass == XmlType.DEFAULT.class) { String defaultObjectFactoryName = type.getPackage().getName() + ".ObjectFactory"; try { factoryClass = Thread.currentThread().getContextClassLoader().loadClass(defaultObjectFactoryName); } catch (Exception e) { factoryClass = type; } } if (factoryClass.getAnnotation(XmlRegistry.class) == null) { return null; } XmlSchema xmlSchema = type.getPackage().getAnnotation(XmlSchema.class); String namespaceURI = getNamespaceURI(xmlType, xmlSchema); for (Method method : factoryClass.getDeclaredMethods()) { XmlElementDecl xmlElementDecl = method.getAnnotation(XmlElementDecl.class); if (xmlElementDecl != null && namespaceURI.equals(getNamespaceURI(xmlElementDecl, xmlSchema))) { if (method.getReturnType() == JAXBElement.class) { Class<?>[] parameterTypes = method.getParameterTypes(); if (parameterTypes.length == 1 && parameterTypes[0] == type) { return method; } } } } return null; } /** * Calculate root element name for an * <code>@XmlRootElement</code> or <code>@XmlType</code>-annotaed type. * * @param type * @return name or <code>null</code> */ public QName getName(Class<?> type) { if (type.getAnnotation(XmlRootElement.class) != null) { return getXmlRootElementName(type); } else if (type.getAnnotation(XmlType.class) != null) { return getXmlTypeName(type); } else { return null; } } /** * Create root element for an * <code>@XmlRootElement</code> or <code>@XmlType</code>-annotaed type. * * @param type * @param value * @return root element (or <code>null</code>) */ public JAXBElement<?> createElement(Class<?> type, Object value) throws JAXBException { if (type.getAnnotation(XmlRootElement.class) != null) { QName name = getXmlRootElementName(type); if (name != null) { @SuppressWarnings({"rawtypes", "unchecked"}) JAXBElement<?> genericElement = new JAXBElement(name, type, value); return genericElement; } } else if (type.getAnnotation(XmlType.class) != null) { Method method = getXmlElementDeclMethod(type); if (method != null) { try { return (JAXBElement<?>) method.invoke(method.getDeclaringClass().newInstance(), value); } catch (Exception e) { throw new JAXBException("Cannot create JAXBElement", e); } } } return null; } }