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

com.fitbur.jackson.databind.introspect.POJOPropertiesCollector Maven / Gradle / Ivy

There is a newer version: 1.0.0
Show newest version
package com.fitbur.jackson.databind.introspect;

import java.lang.reflect.Modifier;
import java.util.*;

import com.fitbur.jackson.databind.*;
import com.fitbur.jackson.databind.cfg.HandlerInstantiator;
import com.fitbur.jackson.databind.cfg.MapperConfig;
import com.fitbur.jackson.databind.util.BeanUtil;
import com.fitbur.jackson.databind.util.ClassUtil;

/**
 * Helper class used for aggregating information about all possible
 * properties of a POJO.
 */
public class POJOPropertiesCollector
{
    /*
    /**********************************************************
    /* Configuration
    /**********************************************************
     */

    /**
     * Configuration settings
     */
    protected final MapperConfig _config;

    /**
     * True if introspection is done for serialization (giving
     * precedence for serialization annotations), or not (false, deserialization)
     */
    protected final boolean _forSerialization;

    /**
     * @since 2.5
     */
    protected final boolean _stdBeanNaming;

    /**
     * Type of POJO for which properties are being collected.
     */
    protected final JavaType _type;

    /**
     * Low-level introspected class information (methods, fields etc)
     */
    protected final AnnotatedClass _classDef;

    protected final VisibilityChecker _visibilityChecker;

    protected final AnnotationIntrospector _annotationIntrospector;

    /**
     * Prefix used by auto-detected mutators ("setters"): usually "set",
     * but differs for builder objects ("with" by default).
     */
    protected final String _mutatorPrefix;
    
    /*
    /**********************************************************
    /* Collected property information
    /**********************************************************
     */

    /**
     * State flag we keep to indicate whether actual property information
     * has been collected or not.
     */
    protected boolean _collected;
    
    /**
     * Set of logical property information collected so far.
     *

* Since 2.6, this has been constructed (more) lazily, to defer * throwing of exceptions for potential conflicts in cases where * this may not be an actual problem. */ protected LinkedHashMap _properties; protected LinkedList _creatorProperties ; protected LinkedList _anyGetters; protected LinkedList _anySetters; /** * Method(s) marked with 'JsonValue' annotation */ protected LinkedList _jsonValueGetters; /** * Lazily collected list of properties that can be implicitly * ignored during serialization; only updated when collecting * information for deserialization purposes */ protected HashSet _ignoredPropertyNames; /** * Lazily collected list of members that were annotated to * indicate that they represent mutators for deserializer * value injection. */ protected LinkedHashMap _injectables; /* /********************************************************** /* Life-cycle /********************************************************** */ protected POJOPropertiesCollector(MapperConfig config, boolean forSerialization, JavaType type, AnnotatedClass classDef, String mutatorPrefix) { _config = config; _stdBeanNaming = config.isEnabled(MapperFeature.USE_STD_BEAN_NAMING); _forSerialization = forSerialization; _type = type; _classDef = classDef; _mutatorPrefix = (mutatorPrefix == null) ? "set" : mutatorPrefix; _annotationIntrospector = config.isAnnotationProcessingEnabled() ? _config.getAnnotationIntrospector() : null; if (_annotationIntrospector == null) { _visibilityChecker = _config.getDefaultVisibilityChecker(); } else { _visibilityChecker = _annotationIntrospector.findAutoDetectVisibility(classDef, _config.getDefaultVisibilityChecker()); } } /* /********************************************************** /* Public API /********************************************************** */ public MapperConfig getConfig() { return _config; } public JavaType getType() { return _type; } public AnnotatedClass getClassDef() { return _classDef; } public AnnotationIntrospector getAnnotationIntrospector() { return _annotationIntrospector; } public List getProperties() { // make sure we return a copy, so caller can remove entries if need be: Map props = getPropertyMap(); return new ArrayList(props.values()); } public Map getInjectables() { if (!_collected) { collectAll(); } return _injectables; } public AnnotatedMethod getJsonValueMethod() { if (!_collected) { collectAll(); } // If @JsonValue defined, must have a single one if (_jsonValueGetters != null) { if (_jsonValueGetters.size() > 1) { reportProblem("Multiple value properties defined ("+_jsonValueGetters.get(0)+" vs " +_jsonValueGetters.get(1)+")"); } // otherwise we won't greatly care return _jsonValueGetters.get(0); } return null; } public AnnotatedMember getAnyGetter() { if (!_collected) { collectAll(); } if (_anyGetters != null) { if (_anyGetters.size() > 1) { reportProblem("Multiple 'any-getters' defined ("+_anyGetters.get(0)+" vs " +_anyGetters.get(1)+")"); } return _anyGetters.getFirst(); } return null; } public AnnotatedMethod getAnySetterMethod() { if (!_collected) { collectAll(); } if (_anySetters != null) { if (_anySetters.size() > 1) { reportProblem("Multiple 'any-setters' defined ("+_anySetters.get(0)+" vs " +_anySetters.get(1)+")"); } return _anySetters.getFirst(); } return null; } /** * Accessor for set of properties that are explicitly marked to be ignored * via per-property markers (but NOT class annotations). */ public Set getIgnoredPropertyNames() { return _ignoredPropertyNames; } /** * Accessor to find out whether type specified requires inclusion * of Object Identifier. */ public ObjectIdInfo getObjectIdInfo() { if (_annotationIntrospector == null) { return null; } ObjectIdInfo info = _annotationIntrospector.findObjectIdInfo(_classDef); if (info != null) { // 2.1: may also have different defaults for refs: info = _annotationIntrospector.findObjectReferenceInfo(_classDef, info); } return info; } /** * Method for finding Class to use as POJO builder, if any. */ public Class findPOJOBuilderClass() { return _annotationIntrospector.findPOJOBuilder(_classDef); } // for unit tests: protected Map getPropertyMap() { if (!_collected) { collectAll(); } return _properties; } /* /********************************************************** /* Public API: main-level collection /********************************************************** */ /** * Method that orchestrates collection activities, and needs to be called * after creating the instance. *

* Since 2.6 has become a no-op and actual collection is done more lazily * at point where properties are actually needed. * * @deprecated Since 2.6; no need to call */ @Deprecated public POJOPropertiesCollector collect() { return this; } /** * Internal method that will collect actual property information. * * @since 2.6 */ protected void collectAll() { LinkedHashMap props = new LinkedHashMap(); // First: gather basic data _addFields(props); _addMethods(props); _addCreators(props); _addInjectables(props); // Remove ignored properties, first; this MUST precede annotation merging // since logic relies on knowing exactly which accessor has which annotation _removeUnwantedProperties(props); // then merge annotations, to simplify further processing for (POJOPropertyBuilder property : props.values()) { property.mergeAnnotations(_forSerialization); } // and then remove unneeded accessors (wrt read-only, read-write) _removeUnwantedAccessor(props); // Rename remaining properties _renameProperties(props); // And use custom naming strategy, if applicable... PropertyNamingStrategy naming = _findNamingStrategy(); if (naming != null) { _renameUsing(props, naming); } /* Sort by visibility (explicit over implicit); drop all but first * of member type (getter, setter etc) if there is visibility * difference */ for (POJOPropertyBuilder property : props.values()) { property.trimByVisibility(); } /* and, if required, apply wrapper name: note, MUST be done after * annotations are merged. */ if (_config.isEnabled(MapperFeature.USE_WRAPPER_NAME_AS_PROPERTY_NAME)) { _renameWithWrappers(props); } // well, almost last: there's still ordering... _sortProperties(props); _properties = props; _collected = true; } /* /********************************************************** /* Overridable internal methods, adding members /********************************************************** */ /** * Method for collecting basic information on all fields found */ protected void _addFields(Map props) { final AnnotationIntrospector ai = _annotationIntrospector; /* 28-Mar-2013, tatu: For deserialization we may also want to remove * final fields, as often they won't make very good mutators... * (although, maybe surprisingly, JVM _can_ force setting of such fields!) */ final boolean pruneFinalFields = !_forSerialization && !_config.isEnabled(MapperFeature.ALLOW_FINAL_FIELDS_AS_MUTATORS); final boolean transientAsIgnoral = _config.isEnabled(MapperFeature.PROPAGATE_TRANSIENT_MARKER); for (AnnotatedField f : _classDef.fields()) { String implName = (ai == null) ? null : ai.findImplicitPropertyName(f); if (implName == null) { implName = f.getName(); } PropertyName pn; if (ai == null) { pn = null; } else if (_forSerialization) { /* 18-Aug-2011, tatu: As per existing unit tests, we should only * use serialization annotation (@JsonSerialize) when serializing * fields, and similarly for deserialize-only annotations... so * no fallbacks in this particular case. */ pn = ai.findNameForSerialization(f); } else { pn = ai.findNameForDeserialization(f); } boolean nameExplicit = (pn != null); if (nameExplicit && pn.isEmpty()) { // empty String meaning "use default name", here just means "same as field name" pn = _propNameFromSimple(implName); nameExplicit = false; } // having explicit name means that field is visible; otherwise need to check the rules boolean visible = (pn != null); if (!visible) { visible = _visibilityChecker.isFieldVisible(f); } // and finally, may also have explicit ignoral boolean ignored = (ai != null) && ai.hasIgnoreMarker(f); // 13-May-2015, tatu: Moved from earlier place (AnnotatedClass) in 2.6 if (f.isTransient()) { visible = false; if (transientAsIgnoral) { ignored = true; } } /* [databind#190]: this is the place to prune final fields, if they are not * to be used as mutators. Must verify they are not explicitly included. * Also: if 'ignored' is set, need to included until a later point, to * avoid losing ignoral information. */ if (pruneFinalFields && (pn == null) && !ignored && Modifier.isFinal(f.getModifiers())) { continue; } _property(props, implName).addField(f, pn, nameExplicit, visible, ignored); } } /** * Method for collecting basic information on constructor(s) found */ protected void _addCreators(Map props) { // can be null if annotation processing is disabled... if (_annotationIntrospector != null) { for (AnnotatedConstructor ctor : _classDef.getConstructors()) { if (_creatorProperties == null) { _creatorProperties = new LinkedList(); } for (int i = 0, len = ctor.getParameterCount(); i < len; ++i) { _addCreatorParam(props, ctor.getParameter(i)); } } for (AnnotatedMethod factory : _classDef.getStaticMethods()) { if (_creatorProperties == null) { _creatorProperties = new LinkedList(); } for (int i = 0, len = factory.getParameterCount(); i < len; ++i) { _addCreatorParam(props, factory.getParameter(i)); } } } } /** * @since 2.4 */ protected void _addCreatorParam(Map props, AnnotatedParameter param) { // JDK 8, paranamer, Scala can give implicit name String impl = _annotationIntrospector.findImplicitPropertyName(param); if (impl == null) { impl = ""; } PropertyName pn = _annotationIntrospector.findNameForDeserialization(param); boolean expl = (pn != null && !pn.isEmpty()); if (!expl) { if (impl.isEmpty()) { /* Important: if neither implicit nor explicit name, can not make use * of this creator parameter -- may or may not be a problem, verified * at a later point. */ return; } // Also: if this occurs, there MUST be explicit annotation on creator itself if (!_annotationIntrospector.hasCreatorAnnotation(param.getOwner())) { return; } pn = PropertyName.construct(impl); } // shouldn't need to worry about @JsonIgnore, since creators only added // if so annotated /* 13-May-2015, tatu: We should try to start with implicit name, similar to how * fields and methods work; but unlike those, we don't necessarily have * implicit name to use (pre-Java8 at least). So: */ POJOPropertyBuilder prop = (expl && impl.isEmpty()) ? _property(props, pn) : _property(props, impl); prop.addCtor(param, pn, expl, true, false); _creatorProperties.add(prop); } /** * Method for collecting basic information on all fields found */ protected void _addMethods(Map props) { final AnnotationIntrospector ai = _annotationIntrospector; for (AnnotatedMethod m : _classDef.memberMethods()) { /* For methods, handling differs between getters and setters; and * we will also only consider entries that either follow the bean * naming convention or are explicitly marked: just being visible * is not enough (unlike with fields) */ int argCount = m.getParameterCount(); if (argCount == 0) { // getters (including 'any getter') _addGetterMethod(props, m, ai); } else if (argCount == 1) { // setters _addSetterMethod(props, m, ai); } else if (argCount == 2) { // any getter? if (ai != null && ai.hasAnySetterAnnotation(m)) { if (_anySetters == null) { _anySetters = new LinkedList(); } _anySetters.add(m); } } } } protected void _addGetterMethod(Map props, AnnotatedMethod m, AnnotationIntrospector ai) { // Very first thing: skip if not returning any value if (!m.hasReturnType()) { return; } // any getter? if (ai != null) { if (ai.hasAnyGetterAnnotation(m)) { if (_anyGetters == null) { _anyGetters = new LinkedList(); } _anyGetters.add(m); return; } // @JsonValue? if (ai.hasAsValueAnnotation(m)) { if (_jsonValueGetters == null) { _jsonValueGetters = new LinkedList(); } _jsonValueGetters.add(m); return; } } String implName; // from naming convention boolean visible; PropertyName pn = (ai == null) ? null : ai.findNameForSerialization(m); boolean nameExplicit = (pn != null); if (!nameExplicit) { // no explicit name; must consider implicit implName = (ai == null) ? null : ai.findImplicitPropertyName(m); if (implName == null) { implName = BeanUtil.okNameForRegularGetter(m, m.getName(), _stdBeanNaming); } if (implName == null) { // if not, must skip implName = BeanUtil.okNameForIsGetter(m, m.getName(), _stdBeanNaming); if (implName == null) { return; } visible = _visibilityChecker.isIsGetterVisible(m); } else { visible = _visibilityChecker.isGetterVisible(m); } } else { // explicit indication of inclusion, but may be empty // we still need implicit name to link with other pieces implName = (ai == null) ? null : ai.findImplicitPropertyName(m); if (implName == null) { implName = BeanUtil.okNameForGetter(m, _stdBeanNaming); } // if not regular getter name, use method name as is if (implName == null) { implName = m.getName(); } if (pn.isEmpty()) { // !!! TODO: use PropertyName for implicit names too pn = _propNameFromSimple(implName); nameExplicit = false; } visible = true; } boolean ignore = (ai == null) ? false : ai.hasIgnoreMarker(m); _property(props, implName).addGetter(m, pn, nameExplicit, visible, ignore); } protected void _addSetterMethod(Map props, AnnotatedMethod m, AnnotationIntrospector ai) { String implName; // from naming convention boolean visible; PropertyName pn = (ai == null) ? null : ai.findNameForDeserialization(m); boolean nameExplicit = (pn != null); if (!nameExplicit) { // no explicit name; must follow naming convention implName = (ai == null) ? null : ai.findImplicitPropertyName(m); if (implName == null) { implName = BeanUtil.okNameForMutator(m, _mutatorPrefix, _stdBeanNaming); } if (implName == null) { // if not, must skip return; } visible = _visibilityChecker.isSetterVisible(m); } else { // explicit indication of inclusion, but may be empty // we still need implicit name to link with other pieces implName = (ai == null) ? null : ai.findImplicitPropertyName(m); if (implName == null) { implName = BeanUtil.okNameForMutator(m, _mutatorPrefix, _stdBeanNaming); } // if not regular getter name, use method name as is if (implName == null) { implName = m.getName(); } if (pn.isEmpty()) { // !!! TODO: use PropertyName for implicit names too pn = _propNameFromSimple(implName); nameExplicit = false; } visible = true; } boolean ignore = (ai == null) ? false : ai.hasIgnoreMarker(m); _property(props, implName).addSetter(m, pn, nameExplicit, visible, ignore); } protected void _addInjectables(Map props) { final AnnotationIntrospector ai = _annotationIntrospector; if (ai == null) { return; } // first fields, then methods for (AnnotatedField f : _classDef.fields()) { _doAddInjectable(ai.findInjectableValueId(f), f); } for (AnnotatedMethod m : _classDef.memberMethods()) { /* for now, only allow injection of a single arg * (to be changed in future) */ if (m.getParameterCount() != 1) { continue; } _doAddInjectable(ai.findInjectableValueId(m), m); } } protected void _doAddInjectable(Object id, AnnotatedMember m) { if (id == null) { return; } if (_injectables == null) { _injectables = new LinkedHashMap(); } AnnotatedMember prev = _injectables.put(id, m); if (prev != null) { String type = id.getClass().getName(); throw new IllegalArgumentException("Duplicate injectable value with id '" +String.valueOf(id)+"' (of type "+type+")"); } } private PropertyName _propNameFromSimple(String simpleName) { return PropertyName.construct(simpleName, null); } /* /********************************************************** /* Internal methods; removing ignored properties /********************************************************** */ /** * Method called to get rid of candidate properties that are marked * as ignored. */ protected void _removeUnwantedProperties(Map props) { Iterator it = props.values().iterator(); while (it.hasNext()) { POJOPropertyBuilder prop = it.next(); // First: if nothing visible, just remove altogether if (!prop.anyVisible()) { it.remove(); continue; } // Otherwise, check ignorals if (prop.anyIgnorals()) { // first: if one or more ignorals, and no explicit markers, remove the whole thing if (!prop.isExplicitlyIncluded()) { it.remove(); _collectIgnorals(prop.getName()); continue; } // otherwise just remove ones marked to be ignored prop.removeIgnored(); if (!_forSerialization && !prop.couldDeserialize()) { _collectIgnorals(prop.getName()); } } } } /** * Method called to further get rid of unwanted individual accessors, * based on read/write settings and rules for "pulling in" accessors * (or not). */ protected void _removeUnwantedAccessor(Map props) { final boolean inferMutators = _config.isEnabled(MapperFeature.INFER_PROPERTY_MUTATORS); Iterator it = props.values().iterator(); while (it.hasNext()) { POJOPropertyBuilder prop = it.next(); prop.removeNonVisible(inferMutators); } } /** * Helper method called to add explicitly ignored properties to a list * of known ignored properties; this helps in proper reporting of * errors. */ private void _collectIgnorals(String name) { if (!_forSerialization) { if (_ignoredPropertyNames == null) { _ignoredPropertyNames = new HashSet(); } _ignoredPropertyNames.add(name); } } /* /********************************************************** /* Internal methods; renaming properties /********************************************************** */ protected void _renameProperties(Map props) { // With renaming need to do in phases: first, find properties to rename Iterator> it = props.entrySet().iterator(); LinkedList renamed = null; while (it.hasNext()) { Map.Entry entry = it.next(); POJOPropertyBuilder prop = entry.getValue(); Collection l = prop.findExplicitNames(); // no explicit names? Implicit one is fine as is if (l.isEmpty()) { continue; } it.remove(); // need to replace with one or more renamed if (renamed == null) { renamed = new LinkedList(); } // simple renaming? Just do it if (l.size() == 1) { PropertyName n = l.iterator().next(); renamed.add(prop.withName(n)); continue; } // but this may be problematic... renamed.addAll(prop.explode(l)); /* String newName = prop.findNewName(); if (newName != null) { if (renamed == null) { renamed = new LinkedList(); } prop = prop.withSimpleName(newName); renamed.add(prop); it.remove(); } */ } // and if any were renamed, merge back in... if (renamed != null) { for (POJOPropertyBuilder prop : renamed) { String name = prop.getName(); POJOPropertyBuilder old = props.get(name); if (old == null) { props.put(name, prop); } else { old.addAll(prop); } // replace the creatorProperty too, if there is one _updateCreatorProperty(prop, _creatorProperties); } } } protected void _renameUsing(Map propMap, PropertyNamingStrategy naming) { POJOPropertyBuilder[] props = propMap.values().toArray(new POJOPropertyBuilder[propMap.size()]); propMap.clear(); for (POJOPropertyBuilder prop : props) { PropertyName fullName = prop.getFullName(); String rename = null; // As per [databind#428] need to skip renaming if property has // explicitly defined name, unless feature is enabled if (!prop.isExplicitlyNamed() || _config.isEnabled(MapperFeature.ALLOW_EXPLICIT_PROPERTY_RENAMING)) { if (_forSerialization) { if (prop.hasGetter()) { rename = naming.nameForGetterMethod(_config, prop.getGetter(), fullName.getSimpleName()); } else if (prop.hasField()) { rename = naming.nameForField(_config, prop.getField(), fullName.getSimpleName()); } } else { if (prop.hasSetter()) { rename = naming.nameForSetterMethod(_config, prop.getSetter(), fullName.getSimpleName()); } else if (prop.hasConstructorParameter()) { rename = naming.nameForConstructorParameter(_config, prop.getConstructorParameter(), fullName.getSimpleName()); } else if (prop.hasField()) { rename = naming.nameForField(_config, prop.getField(), fullName.getSimpleName()); } else if (prop.hasGetter()) { /* Plus, when getter-as-setter is used, need to convert that too.. * (should we verify that's enabled? For now, assume it's ok always) */ rename = naming.nameForGetterMethod(_config, prop.getGetter(), fullName.getSimpleName()); } } } final String simpleName; if (rename != null && !fullName.hasSimpleName(rename)) { prop = prop.withSimpleName(rename); simpleName = rename; } else { simpleName = fullName.getSimpleName(); } /* As per [JACKSON-687], need to consider case where there may already be * something in there... */ POJOPropertyBuilder old = propMap.get(simpleName); if (old == null) { propMap.put(simpleName, prop); } else { old.addAll(prop); } // replace the creatorProperty too, if there is one _updateCreatorProperty(prop, _creatorProperties); } } protected void _renameWithWrappers(Map props) { /* 11-Sep-2012, tatu: To support 'MapperFeature.USE_WRAPPER_NAME_AS_PROPERTY_NAME', * need another round of renaming... */ Iterator> it = props.entrySet().iterator(); LinkedList renamed = null; while (it.hasNext()) { Map.Entry entry = it.next(); POJOPropertyBuilder prop = entry.getValue(); AnnotatedMember member = prop.getPrimaryMember(); if (member == null) { continue; } PropertyName wrapperName = _annotationIntrospector.findWrapperName(member); // One trickier part (wrt [Issue#24] of JAXB annotations: wrapper that // indicates use of actual property... But hopefully has been taken care // of previously if (wrapperName == null || !wrapperName.hasSimpleName()) { continue; } if (!wrapperName.equals(prop.getFullName())) { if (renamed == null) { renamed = new LinkedList(); } prop = prop.withName(wrapperName); renamed.add(prop); it.remove(); } } // and if any were renamed, merge back in... if (renamed != null) { for (POJOPropertyBuilder prop : renamed) { String name = prop.getName(); POJOPropertyBuilder old = props.get(name); if (old == null) { props.put(name, prop); } else { old.addAll(prop); } } } } /* /********************************************************** /* Overridable internal methods, sorting, other stuff /********************************************************** */ /* First, order by [JACKSON-90] (explicit ordering and/or alphabetic) * and then for [JACKSON-170] (implicitly order creator properties before others) */ protected void _sortProperties(Map props) { // Then how about explicit ordering? AnnotationIntrospector intr = _annotationIntrospector; boolean sort; Boolean alpha = (intr == null) ? null : intr.findSerializationSortAlphabetically((Annotated) _classDef); if (alpha == null) { sort = _config.shouldSortPropertiesAlphabetically(); } else { sort = alpha.booleanValue(); } String[] propertyOrder = (intr == null) ? null : intr.findSerializationPropertyOrder(_classDef); // no sorting? no need to shuffle, then if (!sort && (_creatorProperties == null) && (propertyOrder == null)) { return; } int size = props.size(); Map all; // Need to (re)sort alphabetically? if (sort) { all = new TreeMap(); } else { all = new LinkedHashMap(size+size); } for (POJOPropertyBuilder prop : props.values()) { all.put(prop.getName(), prop); } Map ordered = new LinkedHashMap(size+size); // Ok: primarily by explicit order if (propertyOrder != null) { for (String name : propertyOrder) { POJOPropertyBuilder w = all.get(name); if (w == null) { // also, as per [JACKSON-268], we will allow use of "implicit" names for (POJOPropertyBuilder prop : props.values()) { if (name.equals(prop.getInternalName())) { w = prop; // plus re-map to external name, to avoid dups: name = prop.getName(); break; } } } if (w != null) { ordered.put(name, w); } } } // And secondly by sorting Creator properties before other unordered properties if (_creatorProperties != null) { /* As per [databind#311], this is bit delicate; but if alphabetic ordering * is mandated, at least ensure creator properties are in alphabetic * order. Related question of creator vs non-creator is punted for now, * so creator properties still fully predate non-creator ones. */ Collection cr; if (sort) { TreeMap sorted = new TreeMap(); for (POJOPropertyBuilder prop : _creatorProperties) { sorted.put(prop.getName(), prop); } cr = sorted.values(); } else { cr = _creatorProperties; } for (POJOPropertyBuilder prop : cr) { ordered.put(prop.getName(), prop); } } // And finally whatever is left (trying to put again will not change ordering) ordered.putAll(all); props.clear(); props.putAll(ordered); } /* /********************************************************** /* Internal methods; helpers /********************************************************** */ protected void reportProblem(String msg) { throw new IllegalArgumentException("Problem with definition of "+_classDef+": "+msg); } protected POJOPropertyBuilder _property(Map props, PropertyName name) { return _property(props, name.getSimpleName()); } // !!! TODO: deprecate, require use of PropertyName protected POJOPropertyBuilder _property(Map props, String implName) { POJOPropertyBuilder prop = props.get(implName); if (prop == null) { prop = new POJOPropertyBuilder(_config, _annotationIntrospector, _forSerialization, PropertyName.construct(implName)); props.put(implName, prop); } return prop; } private PropertyNamingStrategy _findNamingStrategy() { Object namingDef = (_annotationIntrospector == null)? null : _annotationIntrospector.findNamingStrategy(_classDef); if (namingDef == null) { return _config.getPropertyNamingStrategy(); } if (namingDef instanceof PropertyNamingStrategy) { return (PropertyNamingStrategy) namingDef; } /* Alas, there's no way to force return type of "either class * X or Y" -- need to throw an exception after the fact */ if (!(namingDef instanceof Class)) { throw new IllegalStateException("AnnotationIntrospector returned PropertyNamingStrategy definition of type " +namingDef.getClass().getName()+"; expected type PropertyNamingStrategy or Class instead"); } Class namingClass = (Class)namingDef; // 09-Nov-2015, tatu: Need to consider pseudo-value of STD, which means "use default" if (namingClass == PropertyNamingStrategy.class) { return null; } if (!PropertyNamingStrategy.class.isAssignableFrom(namingClass)) { throw new IllegalStateException("AnnotationIntrospector returned Class " +namingClass.getName()+"; expected Class"); } HandlerInstantiator hi = _config.getHandlerInstantiator(); if (hi != null) { PropertyNamingStrategy pns = hi.namingStrategyInstance(_config, _classDef, namingClass); if (pns != null) { return pns; } } return (PropertyNamingStrategy) ClassUtil.createInstance(namingClass, _config.canOverrideAccessModifiers()); } protected void _updateCreatorProperty(POJOPropertyBuilder prop, List creatorProperties) { if (creatorProperties != null) { for (int i = 0, len = creatorProperties.size(); i < len; ++i) { if (creatorProperties.get(i).getInternalName().equals(prop.getInternalName())) { creatorProperties.set(i, prop); break; } } } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy