Search in sources :

Example 11 with XmlRootElement

use of javax.xml.bind.annotation.XmlRootElement in project sis by apache.

the class RenameListGenerator method add.

/**
 * Gets the namespaces, types and properties for the given class.
 * Properties defined in super-classes will be copied as if they were declared in-line.
 * Those information are memorized for future listing with {@link #print(Appendable)}.
 *
 * @throws SchemaException if two properties have the same name in the same class and namespace.
 */
private void add(Class<?> classe) throws SchemaException {
    XmlRootElement root = classe.getDeclaredAnnotation(XmlRootElement.class);
    if (root != null) {
        /*
             * Add the following entry:
             *
             *     http://a.namespace
             *      PX_AClass
             *       …
             *
             * Then list all properties below "PX_AClass". Note that the namespace may change because properties
             * may be declared in different namespaces, but the class name stay the same. If the same properties
             * are inherited by many classes, they will be repeated in each subclass.
             */
        final String topLevelTypeName = root.name();
        String classNS = namespace(classe, root.namespace());
        for (; ; classNS = namespace(classe, root.namespace())) {
            for (final Method method : classe.getDeclaredMethods()) {
                if (!method.isBridge()) {
                    final XmlElement xe = method.getDeclaredAnnotation(XmlElement.class);
                    if (xe != null) {
                        String namespace = xe.namespace();
                        if (namespace.equals(DEFAULT)) {
                            namespace = classNS;
                        }
                        add(namespace, topLevelTypeName, xe.name());
                    }
                }
            }
            classe = classe.getSuperclass();
            root = classe.getDeclaredAnnotation(XmlRootElement.class);
            if (root == null)
                break;
        }
    } else {
        /*
             * In Apache SIS implementation, classes without JAXB annotation except on a single method are
             * code lists or enumerations. Those classes have exactly one method annotated with @XmlElement,
             * and that method actually gives a type, not a property (because of the way OGC/ISO wrap every
             * properties in a type).
             */
        XmlElement singleton = null;
        for (final Method method : classe.getDeclaredMethods()) {
            final XmlElement xe = method.getDeclaredAnnotation(XmlElement.class);
            if (xe != null) {
                if (singleton != null)
                    return;
                singleton = xe;
            }
        }
    }
}
Also used : XmlRootElement(javax.xml.bind.annotation.XmlRootElement) XmlElement(javax.xml.bind.annotation.XmlElement) Method(java.lang.reflect.Method)

Example 12 with XmlRootElement

use of javax.xml.bind.annotation.XmlRootElement in project sis by apache.

the class AnnotationConsistencyCheck method testImplementationAnnotations.

/**
 * Tests the annotations on every SIS implementations of the interfaces enumerated
 * in the {@link #types} array. More specifically this method tests that:
 *
 * <ul>
 *   <li>All implementation classes have {@link XmlRootElement} and {@link XmlType} annotations.</li>
 *   <li>The name declared in the {@code XmlType} annotations matches the
 *       {@link #getExpectedXmlTypeName expected value}.</li>
 *   <li>The name declared in the {@code XmlRootElement} annotations matches the identifier declared
 *       in the {@link UML} annotation of the GeoAPI interfaces, with {@code "Abstract"} prefix added
 *       if needed.</li>
 *   <li>The namespace declared in the {@code XmlRootElement} annotations is not redundant with
 *       the {@link XmlSchema} annotation in the package.</li>
 * </ul>
 *
 * This method does not check the method annotations, since it is {@link #testMethodAnnotations()} job.
 */
@Test
@DependsOnMethod("testInterfaceAnnotations")
public void testImplementationAnnotations() {
    for (final Class<?> type : types) {
        if (CodeList.class.isAssignableFrom(type)) {
            // Skip code lists, since they are not the purpose of this test.
            continue;
        }
        testingClass = type.getCanonicalName();
        /*
             * Get the implementation class, which is mandatory (otherwise the
             * subclass shall not include the interface in the 'types' array).
             */
        final Class<?> impl = getImplementation(type);
        assertNotNull("No implementation found.", impl);
        assertNotSame("No implementation found.", type, impl);
        testingClass = impl.getCanonicalName();
        /*
             * Compare the XmlRootElement with the UML annotation, if any. The UML annotation
             * is mandatory in the default implementation of the 'testInterfaceAnnotations()'
             * method, but we don't require the UML to be non-null here since this is not the
             * job of this test method. This is because subclasses may choose to override the
             * 'testInterfaceAnnotations()' method.
             */
        final XmlRootElement root = impl.getAnnotation(XmlRootElement.class);
        assertNotNull("Missing @XmlRootElement annotation.", root);
        final UML uml = type.getAnnotation(UML.class);
        // More tests on development branch (removed on trunk because test depends on GeoAPI 3.1)
        /*
             * Check that the namespace is the expected one (according subclass)
             * and is not redundant with the package @XmlSchema annotation.
             */
        assertExpectedNamespace(root.namespace(), impl, uml);
        /*
             * Compare the XmlType annotation with the expected value.
             */
        final XmlType xmlType = impl.getAnnotation(XmlType.class);
        assertNotNull("Missing @XmlType annotation.", xmlType);
    // More tests on development branch (removed on trunk because test depends on GeoAPI 3.1)
    }
}
Also used : XmlRootElement(javax.xml.bind.annotation.XmlRootElement) UML(org.opengis.annotation.UML) XmlType(javax.xml.bind.annotation.XmlType) Test(org.junit.Test) DependsOnMethod(org.apache.sis.test.DependsOnMethod)

Example 13 with XmlRootElement

use of javax.xml.bind.annotation.XmlRootElement in project sis by apache.

the class PackageVerifier method verify.

/**
 * Verifies {@code @XmlType} and {@code @XmlRootElement} on the class. This method verifies naming convention
 * (type name should be same as root element name with {@value SchemaCompliance#TYPE_SUFFIX} suffix appended),
 * ensures that the name exists in the schema, and checks the namespace.
 *
 * @param  type  the class on which to verify annotations.
 */
final void verify(final Class<?> type) throws IOException, ParserConfigurationException, SAXException, SchemaException {
    /*
         * Reinitialize fields to be updated for each class.
         */
    classNS = null;
    currentClass = type;
    isDeprecatedClass = false;
    properties = Collections.emptyMap();
    final XmlType xmlType = type.getDeclaredAnnotation(XmlType.class);
    final XmlRootElement xmlRoot = type.getDeclaredAnnotation(XmlRootElement.class);
    XmlElement codeList = null;
    /*
         * Get the type name and namespace from the @XmlType or @XmlRootElement annotations.
         * If both of them are present, verify that they are consistent (same namespace and
         * same name with "_Type" suffix in @XmlType). If the type name is not declared, we
         * assume that it is the same than the class name (this is what Apache SIS 0.8 does
         * in its org.apache.sis.internal.jaxb.code package for CodeList adapters).
         */
    // ISO class name (not the same than Java class name).
    final String isoName;
    if (xmlRoot != null) {
        classNS = xmlRoot.namespace();
        isoName = xmlRoot.name();
        if (xmlType != null) {
            if (!classNS.equals(xmlType.namespace())) {
                throw new SchemaException(errorInClassMember(null).append("Mismatched namespace in @XmlType and @XmlRootElement."));
            }
            SchemaCompliance.verifyNamingConvention(type.getName(), isoName, xmlType.name(), SchemaCompliance.TYPE_SUFFIX);
        }
    } else if (xmlType != null) {
        classNS = xmlType.namespace();
        final String name = xmlType.name();
        isoName = SchemaCompliance.trim(name, SchemaCompliance.TYPE_SUFFIX);
    } else {
        /*
             * If there is neither @XmlRootElement or @XmlType annotation, it may be a code list as implemented
             * in the org.apache.sis.internal.jaxb.code package. Those adapters have a single @XmlElement which
             * is to be interpreted as if it was the actual type.
             */
        for (final Method method : type.getDeclaredMethods()) {
            final XmlElement e = method.getDeclaredAnnotation(XmlElement.class);
            if (e != null) {
                if (codeList != null)
                    return;
                codeList = e;
            }
        }
        if (codeList == null)
            return;
        classNS = codeList.namespace();
        isoName = codeList.name();
    }
    /*
         * Verify that the namespace declared on the class is not redundant with the namespace
         * declared in the package. Actually redundant namespaces are not wrong, but we try to
         * reduce code size.
         */
    if (classNS.equals(AnnotationConsistencyCheck.DEFAULT)) {
        classNS = packageNS;
    } else if (classNS.equals(packageNS)) {
        throw new SchemaException(errorInClassMember(null).append("Redundant namespace declaration: ").append(classNS));
    }
    /*
         * Verify that the namespace has a prefix associated to it in the package-info file.
         */
    if (namespaceIsUsed.put(classNS, Boolean.TRUE) == null) {
        throw new SchemaException(errorInClassMember(null).append("No prefix in package-info for ").append(classNS));
    }
    /*
         * Properties in the legacy GMD or GMI namespaces may be deprecated, depending if a replacement
         * is already available or not. However properties in other namespaces should not be deprecated.
         * Some validations of deprecated properties are skipped because we didn't loaded their schema.
         */
    isDeprecatedClass = (LEGACY_NAMESPACES.get(classNS) == ALL);
    if (!isDeprecatedClass) {
        if (type.isAnnotationPresent(Deprecated.class)) {
            throw new SchemaException(errorInClassMember(null).append("Unexpected @Deprecated annotation."));
        }
        /*
             * Verify that class name exists, then verify its namespace (associated to the null key by convention).
             */
        properties = schemas.typeDefinition(isoName);
        if (properties == null) {
            throw new SchemaException(errorInClassMember(null).append("Unknown name declared in @XmlRootElement: ").append(isoName));
        }
        final String expectedNS = properties.get(null).namespace;
        if (!classNS.equals(expectedNS)) {
            throw new SchemaException(errorInClassMember(null).append(isoName).append(" shall be associated to namespace ").append(expectedNS));
        }
        // If the class was a code list, we are done.
        if (codeList != null)
            return;
    }
    /*
         * At this point the classNS, className, isDeprecatedClass and properties field have been set.
         * We can now loop over the XML elements, which may be on fields or on methods (public or private).
         */
    for (final Field field : type.getDeclaredFields()) {
        Class<?> valueType = field.getType();
        final boolean isCollection = Collection.class.isAssignableFrom(valueType);
        if (isCollection) {
            valueType = Classes.boundOfParameterizedProperty(field);
        }
        verify(field, field.getName(), valueType, isCollection);
    }
    for (final Method method : type.getDeclaredMethods()) {
        Class<?> valueType = method.getReturnType();
        final boolean isCollection = Collection.class.isAssignableFrom(valueType);
        if (isCollection) {
            valueType = Classes.boundOfParameterizedProperty(method);
        }
        verify(method, method.getName(), valueType, isCollection);
    }
}
Also used : XmlRootElement(javax.xml.bind.annotation.XmlRootElement) Field(java.lang.reflect.Field) XmlElement(javax.xml.bind.annotation.XmlElement) Method(java.lang.reflect.Method) XmlType(javax.xml.bind.annotation.XmlType)

Example 14 with XmlRootElement

use of javax.xml.bind.annotation.XmlRootElement in project candlepin by candlepin.

the class CandlepinSwaggerModelConverter method resolve.

public Model resolve(Type rawType, ModelConverterContext context, Iterator<ModelConverter> next) {
    if (this.shouldIgnoreClass(rawType)) {
        return null;
    }
    /**
     * See java doc of NestedComplexType. This unwrapping makes sure that a
     * real type of field used throughout the method. At the same time flag
     * 'isNested' helps to indicate later in the method that this type may
     * be introspected as Hateoas enabled field
     */
    boolean isNested = false;
    if (rawType instanceof NestedComplexType) {
        isNested = true;
        NestedComplexType nested = (NestedComplexType) rawType;
        rawType = nested.getOriginalType();
    }
    JavaType type = pMapper.constructType(rawType);
    if (type.isEnumType() || PrimitiveType.fromType(type) != null) {
        // We don't build models for primitive types
        return null;
    }
    final BeanDescription beanDesc = pMapper.getSerializationConfig().introspect(type);
    // Couple of possibilities for defining
    String name = isNested ? "Nested" : "";
    name += pTypeName(type, beanDesc);
    if ("Object".equals(name)) {
        return new ModelImpl();
    }
    final ModelImpl model = new ModelImpl().type(ModelImpl.OBJECT).name(name).description(pDescription(beanDesc.getClassInfo()));
    if (!type.isContainerType()) {
        // define the model here to support self/cyclic referencing of
        // models
        context.defineModel(name, model, type, null);
    }
    if (type.isContainerType()) {
        // We treat collections as primitive types, just need to add models
        // for values (if any)
        context.resolve(type.getContentType());
        return null;
    }
    // if XmlRootElement annotation, construct an Xml object and attach it
    // to the model
    XmlRootElement rootAnnotation = beanDesc.getClassAnnotations().get(XmlRootElement.class);
    if (rootAnnotation != null && !"".equals(rootAnnotation.name()) && !"##default".equals(rootAnnotation.name())) {
        log.debug(rootAnnotation.toString());
        Xml xml = new Xml().name(rootAnnotation.name());
        if (rootAnnotation.namespace() != null && !"".equals(rootAnnotation.namespace()) && !"##default".equals(rootAnnotation.namespace())) {
            xml.namespace(rootAnnotation.namespace());
        }
        model.xml(xml);
    }
    // see if @JsonIgnoreProperties exist
    Set<String> propertiesToIgnore = new HashSet<>();
    JsonIgnoreProperties ignoreProperties = beanDesc.getClassAnnotations().get(JsonIgnoreProperties.class);
    if (ignoreProperties != null) {
        propertiesToIgnore.addAll(Arrays.asList(ignoreProperties.value()));
    }
    final ApiModel apiModel = beanDesc.getClassAnnotations().get(ApiModel.class);
    String disc = (apiModel == null) ? "" : apiModel.discriminator();
    if (apiModel != null && StringUtils.isNotEmpty(apiModel.reference())) {
        model.setReference(apiModel.reference());
    }
    if (disc.isEmpty()) {
        // longer method would involve
        // AnnotationIntrospector.findTypeResolver(...) but:
        JsonTypeInfo typeInfo = beanDesc.getClassAnnotations().get(JsonTypeInfo.class);
        if (typeInfo != null) {
            disc = typeInfo.property();
        }
    }
    if (!disc.isEmpty()) {
        model.setDiscriminator(disc);
    }
    List<Property> props = new ArrayList<>();
    for (BeanPropertyDefinition propDef : beanDesc.findProperties()) {
        parseProperty(context, isNested, beanDesc, propertiesToIgnore, props, propDef);
    }
    Collections.sort(props, getPropertyComparator());
    Map<String, Property> modelProps = new LinkedHashMap<>();
    for (Property prop : props) {
        modelProps.put(prop.getName(), prop);
    }
    model.setProperties(modelProps);
    /**
     * This must be done after model.setProperties so that the model's set
     * of properties is available to filter from any subtypes
     */
    if (!resolveSubtypes(model, beanDesc, context)) {
        model.setDiscriminator(null);
    }
    return model;
}
Also used : XmlRootElement(javax.xml.bind.annotation.XmlRootElement) BeanDescription(com.fasterxml.jackson.databind.BeanDescription) ArrayList(java.util.ArrayList) ApiModel(io.swagger.annotations.ApiModel) JsonTypeInfo(com.fasterxml.jackson.annotation.JsonTypeInfo) JsonIgnoreProperties(com.fasterxml.jackson.annotation.JsonIgnoreProperties) LinkedHashMap(java.util.LinkedHashMap) JavaType(com.fasterxml.jackson.databind.JavaType) Xml(io.swagger.models.Xml) BeanPropertyDefinition(com.fasterxml.jackson.databind.introspect.BeanPropertyDefinition) ModelImpl(io.swagger.models.ModelImpl) JsonProperty(com.fasterxml.jackson.annotation.JsonProperty) StringProperty(io.swagger.models.properties.StringProperty) ArrayProperty(io.swagger.models.properties.ArrayProperty) Property(io.swagger.models.properties.Property) MapProperty(io.swagger.models.properties.MapProperty) UUIDProperty(io.swagger.models.properties.UUIDProperty) ApiModelProperty(io.swagger.annotations.ApiModelProperty) AbstractNumericProperty(io.swagger.models.properties.AbstractNumericProperty) RefProperty(io.swagger.models.properties.RefProperty) IntegerProperty(io.swagger.models.properties.IntegerProperty) HashSet(java.util.HashSet)

Example 15 with XmlRootElement

use of javax.xml.bind.annotation.XmlRootElement in project jbpm by kiegroup.

the class JaxbTaskSerializationTest method taskCmdUniqueRootElementTest.

@Test
public void taskCmdUniqueRootElementTest() throws Exception {
    Set<String> uniqueRootElemSet = new HashSet<String>();
    for (Class<?> jaxbClass : reflections.getTypesAnnotatedWith(XmlRootElement.class)) {
        XmlRootElement xmlRootElemAnno = jaxbClass.getAnnotation(XmlRootElement.class);
        assertTrue(xmlRootElemAnno.name() + " is not a unique @XmlRootElement value!", uniqueRootElemSet.add(xmlRootElemAnno.name()));
    }
}
Also used : XmlRootElement(javax.xml.bind.annotation.XmlRootElement) Matchers.anyString(org.mockito.Matchers.anyString) HashSet(java.util.HashSet) Test(org.junit.Test)

Aggregations

XmlRootElement (javax.xml.bind.annotation.XmlRootElement)39 XmlSchema (javax.xml.bind.annotation.XmlSchema)11 XmlType (javax.xml.bind.annotation.XmlType)9 QName (javax.xml.namespace.QName)9 LinkedHashSet (java.util.LinkedHashSet)6 TreeSet (java.util.TreeSet)6 TypeElement (javax.lang.model.element.TypeElement)6 AnnotationProcessorHelper.findTypeElement (org.apache.camel.tools.apt.AnnotationProcessorHelper.findTypeElement)6 Method (java.lang.reflect.Method)5 TypeMirror (javax.lang.model.type.TypeMirror)5 Elements (javax.lang.model.util.Elements)5 XmlElements (javax.xml.bind.annotation.XmlElements)5 Metadata (org.apache.camel.spi.Metadata)5 HashSet (java.util.HashSet)4 Test (org.junit.Test)4 XmlAccessorType (javax.xml.bind.annotation.XmlAccessorType)3 JsonIgnoreProperties (com.fasterxml.jackson.annotation.JsonIgnoreProperties)2 JsonProperty (com.fasterxml.jackson.annotation.JsonProperty)2 JsonTypeInfo (com.fasterxml.jackson.annotation.JsonTypeInfo)2 BeanDescription (com.fasterxml.jackson.databind.BeanDescription)2