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

com.fasterxml.jackson.databind.AnnotationIntrospector Maven / Gradle / Ivy

There is a newer version: 2.17.0
Show newest version
package com.fasterxml.jackson.databind;

import java.lang.annotation.Annotation;
import java.util.*;

import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonInclude;

import com.fasterxml.jackson.core.Version;
import com.fasterxml.jackson.core.Versioned;

import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.cfg.MapperConfig;
import com.fasterxml.jackson.databind.deser.ValueInstantiator;
import com.fasterxml.jackson.databind.introspect.*;
import com.fasterxml.jackson.databind.jsontype.NamedType;
import com.fasterxml.jackson.databind.jsontype.TypeResolverBuilder;
import com.fasterxml.jackson.databind.util.NameTransformer;

/**
 * Abstract class that defines API used for introspecting annotation-based
 * configuration for serialization and deserialization. Separated
 * so that different sets of annotations can be supported, and support
 * plugged-in dynamically.
 *

* NOTE: due to rapid addition of new methods (and changes to existing methods), * it is strongly recommended that custom implementations should not directly * extend this class, but rather extend {@link NopAnnotationIntrospector}. * This way added methods will not break backwards compatibility of custom annotation * introspectors. */ public abstract class AnnotationIntrospector implements Versioned { /* /********************************************************** /* Helper types /********************************************************** */ /** * Value type used with managed and back references; contains type and * logic name, used to link related references */ public static class ReferenceProperty { public enum Type { /** * Reference property that Jackson manages and that is serialized normally (by serializing * reference object), but is used for resolving back references during * deserialization. * Usually this can be defined by using * {@link com.fasterxml.jackson.annotation.JsonManagedReference} */ MANAGED_REFERENCE /** * Reference property that Jackson manages by suppressing it during serialization, * and reconstructing during deserialization. * Usually this can be defined by using * {@link com.fasterxml.jackson.annotation.JsonBackReference} */ ,BACK_REFERENCE ; } private final Type _type; private final String _name; public ReferenceProperty(Type t, String n) { _type = t; _name = n; } public static ReferenceProperty managed(String name) { return new ReferenceProperty(Type.MANAGED_REFERENCE, name); } public static ReferenceProperty back(String name) { return new ReferenceProperty(Type.BACK_REFERENCE, name); } public Type getType() { return _type; } public String getName() { return _name; } public boolean isManagedReference() { return _type == Type.MANAGED_REFERENCE; } public boolean isBackReference() { return _type == Type.BACK_REFERENCE; } } /* /********************************************************** /* Factory methods /********************************************************** */ /** * Factory method for accessing "no operation" implementation * of introspector: instance that will never find any annotation-based * configuration. */ public static AnnotationIntrospector nopInstance() { return NopAnnotationIntrospector.instance; } public static AnnotationIntrospector pair(AnnotationIntrospector a1, AnnotationIntrospector a2) { return new AnnotationIntrospectorPair(a1, a2); } /* /********************************************************** /* Access to possibly chained introspectors (1.7) /********************************************************** */ /** * Method that can be used to collect all "real" introspectors that * this introspector contains, if any; or this introspector * if it is not a container. Used to get access to all container * introspectors in their priority order. *

* Default implementation returns a Singleton list with this introspector * as contents. * This usually works for sub-classes, except for proxy or delegating "container * introspectors" which need to override implementation. */ public Collection allIntrospectors() { return Collections.singletonList(this); } /** * Method that can be used to collect all "real" introspectors that * this introspector contains, if any; or this introspector * if it is not a container. Used to get access to all container * introspectors in their priority order. *

* Default implementation adds this introspector in result; this usually * works for sub-classes, except for proxy or delegating "container * introspectors" which need to override implementation. */ public Collection allIntrospectors(Collection result) { result.add(this); return result; } /* /********************************************************** /* Default Versioned impl /********************************************************** */ // @Override public abstract Version version(); /* /********************************************************** /* Meta-annotations (annotations for annotation types) /********************************************************** */ /** * Method called by framework to determine whether given annotation * is handled by this introspector. * * @deprecated Not used since 2.0; deprecated sicne 2.1 */ @Deprecated public boolean isHandled(Annotation ann) { return false; } /** * Method for checking whether given annotation is considered an * annotation bundle: if so, all meta-annotations it has will * be used instead of annotation ("bundle") itself. * * @since 2.0 */ public boolean isAnnotationBundle(Annotation ann) { return false; } /* /********************************************************** /* General annotations (for classes, properties) /********************************************************** */ /** * Method for checking whether given annotated thing * (type, or accessor) indicates that values * referenced (values of type of annotated class, or * values referenced by annotated property; latter * having precedence) should include Object Identifier, * and if so, specify details of Object Identity used. * * @since 2.0 */ public ObjectIdInfo findObjectIdInfo(Annotated ann) { return null; } /** * Method for figuring out additional properties of an Object Identity reference * * @since 2.1 */ public ObjectIdInfo findObjectReferenceInfo(Annotated ann, ObjectIdInfo objectIdInfo) { return objectIdInfo; } /* /********************************************************** /* General class annotations /********************************************************** */ /** * Method for locating name used as "root name" (for use by * some serializers when outputting root-level object -- mostly * for XML compatibility purposes) for given class, if one * is defined. Returns null if no declaration found; can return * explicit empty String, which is usually ignored as well as null. *

* NOTE: method signature changed in 2.1, to return {@link PropertyName} * instead of String. */ public PropertyName findRootName(AnnotatedClass ac) { return null; } /** * Method for finding list of properties to ignore for given class * (null is returned if not specified). * List of property names is applied * after other detection mechanisms, to filter out these specific * properties from being serialized and deserialized. */ public String[] findPropertiesToIgnore(Annotated ac) { return null; } /** * Method for checking whether an annotation indicates that all unknown properties */ public Boolean findIgnoreUnknownProperties(AnnotatedClass ac) { return null; } /** * Method for checking whether properties that have specified type * (class, not generics aware) should be completely ignored for * serialization and deserialization purposes. * * @param ac Type to check * * @return Boolean.TRUE if properties of type should be ignored; * Boolean.FALSE if they are not to be ignored, null for default * handling (which is 'do not ignore') */ public Boolean isIgnorableType(AnnotatedClass ac) { return null; } /** * Method for finding if annotated class has associated filter; and if so, * to return id that is used to locate filter. * * @return Id of the filter to use for filtering properties of annotated * class, if any; or null if none found. */ public Object findFilterId(AnnotatedClass ac) { return null; } /** * Method for finding {@link PropertyNamingStrategy} for given * class, if any specified by annotations; and if so, either return * a {@link PropertyNamingStrategy} instance, or Class to use for * creating instance * * @return Sub-class or instance of {@link PropertyNamingStrategy}, if one * is specified for given class; null if not. * * @since 2.1 */ public Object findNamingStrategy(AnnotatedClass ac) { return null; } /* /********************************************************** /* Property auto-detection /********************************************************** */ /** * Method for checking if annotations indicate changes to minimum visibility levels * needed for auto-detecting property elements (fields, methods, constructors). * A baseline checker is given, and introspector is to either return it as is * (if no annotations are found), or build and return a derived instance (using * checker's build methods). */ public VisibilityChecker findAutoDetectVisibility(AnnotatedClass ac, VisibilityChecker checker) { return checker; } /* /********************************************************** /* Class annotations for Polymorphic type handling (1.5+) /********************************************************** */ /** * Method for checking if given class has annotations that indicate * that specific type resolver is to be used for handling instances. * This includes not only * instantiating resolver builder, but also configuring it based on * relevant annotations (not including ones checked with a call to * {@link #findSubtypes} * * @param config Configuration settings in effect (for serialization or deserialization) * @param ac Annotated class to check for annotations * @param baseType Base java type of value for which resolver is to be found * * @return Type resolver builder for given type, if one found; null if none */ public TypeResolverBuilder findTypeResolver(MapperConfig config, AnnotatedClass ac, JavaType baseType) { return null; } /** * Method for checking if given property entity (field or method) has annotations * that indicate that specific type resolver is to be used for handling instances. * This includes not only * instantiating resolver builder, but also configuring it based on * relevant annotations (not including ones checked with a call to * {@link #findSubtypes} * * @param config Configuration settings in effect (for serialization or deserialization) * @param am Annotated member (field or method) to check for annotations * @param baseType Base java type of property for which resolver is to be found * * @return Type resolver builder for properties of given entity, if one found; * null if none */ public TypeResolverBuilder findPropertyTypeResolver(MapperConfig config, AnnotatedMember am, JavaType baseType) { return null; } /** * Method for checking if given structured property entity (field or method that * has nominal value of Map, Collection or array type) has annotations * that indicate that specific type resolver is to be used for handling type * information of contained values. * This includes not only * instantiating resolver builder, but also configuring it based on * relevant annotations (not including ones checked with a call to * {@link #findSubtypes} * * @param config Configuration settings in effect (for serialization or deserialization) * @param am Annotated member (field or method) to check for annotations * @param containerType Type of property for which resolver is to be found (must be a container type) * * @return Type resolver builder for values contained in properties of given entity, * if one found; null if none */ public TypeResolverBuilder findPropertyContentTypeResolver(MapperConfig config, AnnotatedMember am, JavaType containerType) { return null; } /** * Method for locating annotation-specified subtypes related to annotated * entity (class, method, field). Note that this is only guaranteed to be * a list of directly * declared subtypes, no recursive processing is guarantees (i.e. caller * has to do it if/as necessary) * * @param a Annotated entity (class, field/method) to check for annotations */ public List findSubtypes(Annotated a) { return null; } /** * Method for checking if specified type has explicit name. * * @param ac Class to check for type name annotations */ public String findTypeName(AnnotatedClass ac) { return null; } /* /********************************************************** /* General member (field, method/constructor) annotations /********************************************************** */ /** * Method for checking if given member indicates that it is part * of a reference (parent/child). */ public ReferenceProperty findReferenceType(AnnotatedMember member) { return null; } /** * Method called to check whether given property is marked to be "unwrapped" * when being serialized (and appropriately handled in reverse direction, * i.e. expect unwrapped representation during deserialization). * Return value is the name transformation to use, if wrapping/unwrapping * should be done, or null if not -- note that transformation may simply * be identity transformation (no changes). */ public NameTransformer findUnwrappingNameTransformer(AnnotatedMember member) { return null; } /** * Method called to check whether given property is marked to * be ignored. This is used to determine whether to ignore * properties, on per-property basis, usually combining * annotations from multiple accessors (getters, setters, fields, * constructor parameters). */ public boolean hasIgnoreMarker(AnnotatedMember m) { return false; } /** * Method called to find out whether given member expectes a value * to be injected, and if so, what is the identifier of the value * to use during injection. * Type if identifier needs to be compatible with provider of * values (of type {@link InjectableValues}); often a simple String * id is used. * * @param m Member to check * * @return Identifier of value to inject, if any; null if no injection * indicator is found */ public Object findInjectableValueId(AnnotatedMember m) { return null; } /** * Method that can be called to check whether this member has * an annotation that suggests whether value for matching property * is required or not. * * @since 2.0 */ public Boolean hasRequiredMarker(AnnotatedMember m) { return null; } /** * Method for checking if annotated property (represented by a field or * getter/setter method) has definitions for views it is to be included in. * If null is returned, no view definitions exist and property is always * included (or always excluded as per default view inclusion configuration); * otherwise it will only be included for views included in returned * array. View matches are checked using class inheritance rules (sub-classes * inherit inclusions of super-classes) * * @param a Annotated property (represented by a method, field or ctor parameter) * @return Array of views (represented by classes) that the property is included in; * if null, always included (same as returning array containing Object.class) */ public Class[] findViews(Annotated a) { return null; } /** * Method for finding format annotations for given member. * Return value is typically used by serializers and/or * deserializers to customize presentation aspects of the * serialized value. * * @since 2.0 * * @deprecated Since 2.1, use {@link #findFormat(Annotated)} instead. */ @Deprecated public JsonFormat.Value findFormat(AnnotatedMember member) { return null; } /** * Method for finding format annotations for property or class. * Return value is typically used by serializers and/or * deserializers to customize presentation aspects of the * serialized value. * * @since 2.1 */ public JsonFormat.Value findFormat(Annotated memberOrClass) { if (memberOrClass instanceof AnnotatedMember) { return findFormat((AnnotatedMember) memberOrClass); } return null; } /** * Method for checking whether given accessor claims to represent * type id: if so, its value may be used as an override, * instead of generated type id. * * @since 2.0 */ public Boolean isTypeId(AnnotatedMember member) { return null; } /** * Method used to check if specified property has annotation that indicates * that it should be wrapped in an element; and if so, name to use. * Note that not all serializers and deserializers support use this method: * currently (2.1) it is only used by XML-backed handlers. * * @return Wrapper name to use, if any, or {@link PropertyName#USE_DEFAULT} * to indicate that no wrapper element should be used. * * @since 2.1 */ public PropertyName findWrapperName(Annotated ann) { return null; } /* /********************************************************** /* Serialization: general annotations /********************************************************** */ /** * Method for getting a serializer definition on specified method * or field. Type of definition is either instance (of type * {@link JsonSerializer}) or Class (of type * Class); if value of different * type is returned, a runtime exception may be thrown by caller. */ public Object findSerializer(Annotated am) { return null; } /** * Method for getting a serializer definition for keys of associated Map property. * Type of definition is either instance (of type * {@link JsonSerializer}) or Class (of type * Class); if value of different * type is returned, a runtime exception may be thrown by caller. */ public Object findKeySerializer(Annotated am) { return null; } /** * Method for getting a serializer definition for content (values) of * associated Collection, array or Map property. * Type of definition is either instance (of type * {@link JsonSerializer}) or Class (of type * Class); if value of different * type is returned, a runtime exception may be thrown by caller. */ public Object findContentSerializer(Annotated am) { return null; } /** * Method for checking whether given annotated entity (class, method, * field) defines which Bean/Map properties are to be included in * serialization. * If no annotation is found, method should return given second * argument; otherwise value indicated by the annotation * * @return Enumerated value indicating which properties to include * in serialization */ public JsonInclude.Include findSerializationInclusion(Annotated a, JsonInclude.Include defValue) { return defValue; } /** * Method for accessing annotated type definition that a * method/field can have, to be used as the type for serialization * instead of the runtime type. * Type returned (if any) needs to be widening conversion (super-type). * Declared return type of the method is also considered acceptable. * * @return Class to use instead of runtime type */ public Class findSerializationType(Annotated a) { return null; } /** * Method for finding possible widening type definition that a property * value can have, to define less specific key type to use for serialization. * It should be only be used with {@link java.util.Map} types. * * @return Class specifying more general type to use instead of * declared type, if annotation found; null if not */ public Class findSerializationKeyType(Annotated am, JavaType baseType) { return null; } /** * Method for finding possible widening type definition that a property * value can have, to define less specific key type to use for serialization. * It should be only used with structured types (arrays, collections, maps). * * @return Class specifying more general type to use instead of * declared type, if annotation found; null if not */ public Class findSerializationContentType(Annotated am, JavaType baseType) { return null; } /** * Method for accessing declared typing mode annotated (if any). * This is used for type detection, unless more granular settings * (such as actual exact type; or serializer to use which means * no type information is needed) take precedence. * * @return Typing mode to use, if annotation is found; null otherwise */ public JsonSerialize.Typing findSerializationTyping(Annotated a) { return null; } /* /********************************************************** /* Serialization: class annotations /********************************************************** */ /** * Method for accessing defined property serialization order (which may be * partial). May return null if no ordering is defined. */ public String[] findSerializationPropertyOrder(AnnotatedClass ac) { return null; } /** * Method for checking whether an annotation indicates that serialized properties * for which no explicit is defined should be alphabetically (lexicograpically) * ordered */ public Boolean findSerializationSortAlphabetically(AnnotatedClass ac) { return null; } /* /********************************************************** /* Serialization: property annotations /********************************************************** */ /** * Method for checking whether given property accessors (method, * field) has an annotation that suggests property name to use * for serialization. * Should return null if no annotation * is found; otherwise a non-null name (possibly * {@link PropertyName#USE_DEFAULT}, which means "use default heuristics"). * * @param a Property accessor to check * * @return Name to use if found; null if not. * * @since 2.1 */ public PropertyName findNameForSerialization(Annotated a) { // [Issue#69], need bit of delegation // !!! TODO: in 2.2, remove old methods? String name; if (a instanceof AnnotatedField) { name = findSerializationName((AnnotatedField) a); } else if (a instanceof AnnotatedMethod) { name = findSerializationName((AnnotatedMethod) a); } else { name = null; } if (name != null) { if (name.length() == 0) { // empty String means 'default' return PropertyName.USE_DEFAULT; } return new PropertyName(name); } return null; } /** * Method for checking whether given method has an annotation * that suggests property name associated with method that * may be a "getter". Should return null if no annotation * is found; otherwise a non-null String. * If non-null value is returned, it is used as the property * name, except for empty String ("") which is taken to mean * "use standard bean name detection if applicable; * method name if not". * * @deprecated Since 2.1 should use {@link #findNameForSerialization} instead */ @Deprecated public String findSerializationName(AnnotatedMethod am) { return null; } /** * Method for checking whether given member field represent * a serializable logical property; and if so, returns the * name of that property. * Should return null if no annotation is found (indicating it * is not a serializable field); otherwise a non-null String. * If non-null value is returned, it is used as the property * name, except for empty String ("") which is taken to mean * "use the field name as is". * * @deprecated Since 2.1 should use {@link #findNameForSerialization} instead */ @Deprecated public String findSerializationName(AnnotatedField af) { return null; } /** * Method for checking whether given method has an annotation * that suggests that the return value of annotated method * should be used as "the value" of the object instance; usually * serialized as a primitive value such as String or number. * * @return True if such annotation is found (and is not disabled); * false if no enabled annotation is found */ public boolean hasAsValueAnnotation(AnnotatedMethod am) { return false; } /** * Method for determining the String value to use for serializing * given enumeration entry; used when serializing enumerations * as Strings (the standard method). * * @return Serialized enum value. */ public String findEnumValue(Enum value) { // as per [JACKSON-875], should use default here return value.name(); } /* /********************************************************** /* Deserialization: general annotations /********************************************************** */ /** * Method for getting a deserializer definition on specified method * or field. * Type of definition is either instance (of type * {@link JsonDeserializer}) or Class (of type * Class); if value of different * type is returned, a runtime exception may be thrown by caller. */ public Object findDeserializer(Annotated am) { return null; } /** * Method for getting a deserializer definition for keys of * associated Map property. * Type of definition is either instance (of type * {@link JsonDeserializer}) or Class (of type * Class); if value of different * type is returned, a runtime exception may be thrown by caller. */ public Object findKeyDeserializer(Annotated am) { return null; } /** * Method for getting a deserializer definition for content (values) of * associated Collection, array or * Map property. * Type of definition is either instance (of type * {@link JsonDeserializer}) or Class (of type * Class); if value of different * type is returned, a runtime exception may be thrown by caller. */ public Object findContentDeserializer(Annotated am) { return null; } /** * Method for accessing annotated type definition that a * method can have, to be used as the type for serialization * instead of the runtime type. * Type must be a narrowing conversion * (i.e.subtype of declared type). * Declared return type of the method is also considered acceptable. * * @param baseType Assumed type before considering annotations * * @return Class to use for deserialization instead of declared type */ public Class findDeserializationType(Annotated am, JavaType baseType) { return null; } /** * Method for accessing additional narrowing type definition that a * method can have, to define more specific key type to use. * It should be only be used with {@link java.util.Map} types. * * @param baseKeyType Assumed key type before considering annotations * * @return Class specifying more specific type to use instead of * declared type, if annotation found; null if not */ public Class findDeserializationKeyType(Annotated am, JavaType baseKeyType) { return null; } /** * Method for accessing additional narrowing type definition that a * method can have, to define more specific content type to use; * content refers to Map values and Collection/array elements. * It should be only be used with Map, Collection and array types. * * @param baseContentType Assumed content (value) type before considering annotations * * @return Class specifying more specific type to use instead of * declared type, if annotation found; null if not */ public Class findDeserializationContentType(Annotated am, JavaType baseContentType) { return null; } /* /********************************************************** /* Deserialization: class annotations /********************************************************** */ /** * Method getting {@link ValueInstantiator} to use for given * type (class): return value can either be an instance of * instantiator, or class of instantiator to create. */ public Object findValueInstantiator(AnnotatedClass ac) { return null; } /** * Method for finding Builder object to use for constructing * value instance and binding data (sort of combining value * instantiators that can construct, and deserializers * that can bind data). *

* Note that unlike accessors for some helper Objects, this * method does not allow returning instances: the reason is * that builders have state, and a separate instance needs * to be created for each deserialization call. * * @since 2.0 */ public Class findPOJOBuilder(AnnotatedClass ac) { return null; } /** * @since 2.0 */ public JsonPOJOBuilder.Value findPOJOBuilderConfig(AnnotatedClass ac) { return null; } /* /********************************************************** /* Deserialization: property annotations /********************************************************** */ /** * Method for checking whether given property accessors (method, * field) has an annotation that suggests property name to use * for deserialization (reading JSON into POJOs). * Should return null if no annotation * is found; otherwise a non-null name (possibly * {@link PropertyName#USE_DEFAULT}, which means "use default heuristics"). * * @param a Property accessor to check * * @return Name to use if found; null if not. * * @since 2.1 */ public PropertyName findNameForDeserialization(Annotated a) { // [Issue#69], need bit of delegation // !!! TODO: in 2.2, remove old methods? String name; if (a instanceof AnnotatedField) { name = findDeserializationName((AnnotatedField) a); } else if (a instanceof AnnotatedMethod) { name = findDeserializationName((AnnotatedMethod) a); } else if (a instanceof AnnotatedParameter) { name = findDeserializationName((AnnotatedParameter) a); } else { name = null; } if (name != null) { if (name.length() == 0) { // empty String means 'default' return PropertyName.USE_DEFAULT; } return new PropertyName(name); } return null; } /** * Method for checking whether given method has an annotation * that suggests property name associated with method that * may be a "setter". Should return null if no annotation * is found; otherwise a non-null String. * If non-null value is returned, it is used as the property * name, except for empty String ("") which is taken to mean * "use standard bean name detection if applicable; * method name if not". * * @deprecated Since 2.1 should use {@link #findNameForDeserialization} instead */ @Deprecated public String findDeserializationName(AnnotatedMethod am) { return null; } /** * Method for checking whether given member field represent * a deserializable logical property; and if so, returns the * name of that property. * Should return null if no annotation is found (indicating it * is not a deserializable field); otherwise a non-null String. * If non-null value is returned, it is used as the property * name, except for empty String ("") which is taken to mean * "use the field name as is". * * @deprecated Since 2.1 should use {@link #findNameForDeserialization} instead */ @Deprecated public String findDeserializationName(AnnotatedField af) { return null; } /** * Method for checking whether given set of annotations indicates * property name for associated parameter. * No actual parameter object can be passed since JDK offers no * representation; just annotations. * * @deprecated Since 2.1 should use {@link #findNameForDeserialization} instead */ @Deprecated public String findDeserializationName(AnnotatedParameter param) { return null; } /** * Method for checking whether given method has an annotation * that suggests that the method is to serve as "any setter"; * method to be used for setting values of any properties for * which no dedicated setter method is found. * * @return True if such annotation is found (and is not disabled), * false otherwise */ public boolean hasAnySetterAnnotation(AnnotatedMethod am) { return false; } /** * Method for checking whether given method has an annotation * that suggests that the method is to serve as "any setter"; * method to be used for accessing set of miscellaneous "extra" * properties, often bound with matching "any setter" method. * * @return True if such annotation is found (and is not disabled), * false otherwise */ public boolean hasAnyGetterAnnotation(AnnotatedMethod am) { return false; } /** * Method for checking whether given annotated item (method, constructor) * has an annotation * that suggests that the method is a "creator" (aka factory) * method to be used for construct new instances of deserialized * values. * * @return True if such annotation is found (and is not disabled), * false otherwise */ public boolean hasCreatorAnnotation(Annotated a) { return false; } /* /********************************************************** /* Helper classes /********************************************************** */ /** * Old version of {@link AnnotationIntrospectorPair}. * * @deprecated Starting with 2.1, use {@link AnnotationIntrospectorPair} instead. */ @Deprecated public static class Pair extends AnnotationIntrospectorPair { private static final long serialVersionUID = 1L; @Deprecated public Pair(AnnotationIntrospector p, AnnotationIntrospector s) { super(p, s); } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy