All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.vmware.vcloud.xjcplugin.JsonMappingInfoPlugin Maven / Gradle / Ivy

There is a newer version: 10.2.2
Show newest version
package com.vmware.vcloud.xjcplugin;

/*-
 * #%L
 * vcd-xjc-plugins :: Custom plugins for XML to Java Compilation
 * %%
 * Copyright (C) 2018 VMware, Inc.
 * %%
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 * 
 * 1. Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 * #L%
 */

import java.util.ArrayList;
import java.util.List;

import org.xml.sax.ErrorHandler;

import com.fasterxml.jackson.annotation.JsonSubTypes;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.sun.codemodel.JAnnotatable;
import com.sun.codemodel.JAnnotationArrayMember;
import com.sun.codemodel.JAnnotationUse;
import com.sun.tools.xjc.Options;
import com.sun.tools.xjc.Plugin;
import com.sun.tools.xjc.model.CCustomizations;
import com.sun.tools.xjc.model.CPluginCustomization;
import com.sun.tools.xjc.outline.ClassOutline;
import com.sun.tools.xjc.outline.Outline;

import org.jvnet.jaxb2_commons.util.CustomizationUtils;

/**
 * JsonMappingInfoPlugin is a plug-in for the JAXB's XJC code generator. It adds
 * {@link JsonTypeInfo} and {@link JsonSubTypes} annotations to the generated JAXB classes. This
 * facilitates mapping between abstract types and JSON objects
 * 

* To activate it, add the following parameters to the XJC command line:
* *

 * -enable -Xjsonapi
 * 
* * Add the following to parent type * in the XSD: * *
 * <xs:appinfo>
 *     <meta:jsonTypeInfo propertyName="type" />
 * </xs:appinfo>
 * 
* * Add the following to any sub type(s) in the XSD: * *
 * <xs:appinfo>
 *     <meta:jsonSubTypeInfo name="string" />
 * </xs:appinfo>
 * 
* * *

* You also have to add the following boilerplate to the beginning of the XSD: * *

 *   xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
 *   xmlns:meta="http://www.vmware.com/vcloud/meta"
 *   jaxb:verion="2.0"
 *   jaxb:extensionBindingPrefixes="meta"
 * 
*/ public class JsonMappingInfoPlugin extends Plugin { private static final String X_ANNOTATION_JSON_TYPE_PROPERTY_NAME = "propertyName"; private static final String X_ANNOTATION_JSON_SUBTYPE_NAME = "name"; private static final String NAMESPACE_URI = "http://www.vmware.com/vcloud/plugin/json"; private static final String ELEMENT_JSON_TYPE = "jsonTypeInfo"; private static final String ELEMENT_JSON_SUBTYPE_TYPE = "jsonSubTypeInfo"; private static final String PLUGIN_OPTION = "Xjson-api"; @Override public String getOptionName() { return PLUGIN_OPTION; } @Override public List getCustomizationURIs() { ArrayList res = new ArrayList(1); res.add(NAMESPACE_URI); return res; } @Override public boolean isCustomizationTagName(String nsUri, String localName) { return NAMESPACE_URI.equals(nsUri) && (ELEMENT_JSON_TYPE.equals(localName) || ELEMENT_JSON_SUBTYPE_TYPE.equals(localName)); } @Override public String getUsage() { return " -" + PLUGIN_OPTION + ": enables the plugin\n"; } @Override public boolean run(Outline outline, Options options, ErrorHandler errorHandler) { for (ClassOutline classOutline : outline.getClasses()) { final CCustomizations customizations = CustomizationUtils.getCustomizations(classOutline); addJsonMappingAnnotations(classOutline, customizations); } return true; } /** * Adds {@link JsonTypeInfo} or {@link JsonSubTypes} annotations to the given element based on * the schema annotations present. * * @param classOutline * {@link ClassOutline} for the element which will be annotated * @param customizations * schema customizations for this element */ private void addJsonMappingAnnotations( final ClassOutline classOutline, final CCustomizations customizations) { final JAnnotatable annotatable = classOutline.implClass; if (annotatable == null) { return; } final CPluginCustomization parentTypeCustomization = customizations.find(NAMESPACE_URI, ELEMENT_JSON_TYPE); if (parentTypeCustomization != null) { String typePropertyName = null; parentTypeCustomization.markAsAcknowledged(); if (parentTypeCustomization.element.hasAttribute(X_ANNOTATION_JSON_TYPE_PROPERTY_NAME)) { typePropertyName = parentTypeCustomization.element.getAttribute(X_ANNOTATION_JSON_TYPE_PROPERTY_NAME); } final JAnnotationUse annotation = annotatable.annotate(JsonTypeInfo.class); annotation.param("use", JsonTypeInfo.Id.NAME); annotation.param("include", JsonTypeInfo.As.PROPERTY); annotation.param("property", typePropertyName); } final CPluginCustomization subTypeCustomization = customizations.find(NAMESPACE_URI, ELEMENT_JSON_SUBTYPE_TYPE); if (subTypeCustomization != null) { String typeName = null; subTypeCustomization.markAsAcknowledged(); if (subTypeCustomization.element.hasAttribute(X_ANNOTATION_JSON_SUBTYPE_NAME)) { typeName = subTypeCustomization.element.getAttribute(X_ANNOTATION_JSON_SUBTYPE_NAME); } final JAnnotatable annotatableParent = classOutline.getSuperClass().implClass; JAnnotationArrayMember annotationValues = null; for (JAnnotationUse annot : annotatableParent.annotations()) { if (annot.getAnnotationClass().fullName().equals(JsonSubTypes.class.getCanonicalName())) { annotationValues = (JAnnotationArrayMember)annot.getAnnotationMembers().get("value"); break; } } if (annotationValues == null) { annotationValues = annotatableParent.annotate(JsonSubTypes.class).paramArray("value"); } annotationValues.annotate(JsonSubTypes.Type.class).param("value", classOutline.implClass).param("name", typeName); } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy