1 package com.fasterxml.jackson.databind.introspect;
2
3 import java.lang.reflect.Modifier;
4 import java.util.*;
5
6 import com.fasterxml.jackson.annotation.JacksonInject;
7 import com.fasterxml.jackson.annotation.JsonCreator;
8 import com.fasterxml.jackson.annotation.JsonProperty;
9
10 import com.fasterxml.jackson.databind.*;
11
12 import com.fasterxml.jackson.databind.cfg.HandlerInstantiator;
13 import com.fasterxml.jackson.databind.cfg.MapperConfig;
14 import com.fasterxml.jackson.databind.util.BeanUtil;
15 import com.fasterxml.jackson.databind.util.ClassUtil;
16
17
21 public class POJOPropertiesCollector
22 {
23
28
29
32 protected final MapperConfig<?> _config;
33
34
38 protected final boolean _forSerialization;
39
40
43 protected final boolean _stdBeanNaming;
44
45
48 protected final JavaType _type;
49
50
53 protected final AnnotatedClass _classDef;
54
55 protected final VisibilityChecker<?> _visibilityChecker;
56
57 protected final AnnotationIntrospector _annotationIntrospector;
58
59
62 protected final boolean _useAnnotations;
63
64
68 protected final String _mutatorPrefix;
69
70
75
76
80 protected boolean _collected;
81
82
89 protected LinkedHashMap<String, POJOPropertyBuilder> _properties;
90
91 protected LinkedList<POJOPropertyBuilder> _creatorProperties;
92
93
107 protected Map<PropertyName, PropertyName> _fieldRenameMappings;
108
109 protected LinkedList<AnnotatedMember> _anyGetters;
110
111 protected LinkedList<AnnotatedMethod> _anySetters;
112
113 protected LinkedList<AnnotatedMember> _anySetterField;
114
115
120 protected LinkedList<AnnotatedMember> _jsonValueAccessors;
121
122
127 protected HashSet<String> _ignoredPropertyNames;
128
129
134 protected LinkedHashMap<Object, AnnotatedMember> _injectables;
135
136
141
142 protected POJOPropertiesCollector(MapperConfig<?> config, boolean forSerialization,
143 JavaType type, AnnotatedClass classDef, String mutatorPrefix)
144 {
145 _config = config;
146 _stdBeanNaming = config.isEnabled(MapperFeature.USE_STD_BEAN_NAMING);
147 _forSerialization = forSerialization;
148 _type = type;
149 _classDef = classDef;
150 _mutatorPrefix = (mutatorPrefix == null) ? "set" : mutatorPrefix;
151 if (config.isAnnotationProcessingEnabled()) {
152 _useAnnotations = true;
153 _annotationIntrospector = _config.getAnnotationIntrospector();
154 } else {
155 _useAnnotations = false;
156 _annotationIntrospector = AnnotationIntrospector.nopInstance();
157 }
158 _visibilityChecker = _config.getDefaultVisibilityChecker(type.getRawClass(),
159 classDef);
160 }
161
162
167
168 public MapperConfig<?> getConfig() {
169 return _config;
170 }
171
172 public JavaType getType() {
173 return _type;
174 }
175
176 public AnnotatedClass getClassDef() {
177 return _classDef;
178 }
179
180 public AnnotationIntrospector getAnnotationIntrospector() {
181 return _annotationIntrospector;
182 }
183
184 public List<BeanPropertyDefinition> getProperties() {
185
186 Map<String, POJOPropertyBuilder> props = getPropertyMap();
187 return new ArrayList<BeanPropertyDefinition>(props.values());
188 }
189
190 public Map<Object, AnnotatedMember> getInjectables() {
191 if (!_collected) {
192 collectAll();
193 }
194 return _injectables;
195 }
196
197
200 public AnnotatedMember getJsonValueAccessor()
201 {
202 if (!_collected) {
203 collectAll();
204 }
205
206 if (_jsonValueAccessors != null) {
207 if (_jsonValueAccessors.size() > 1) {
208 reportProblem("Multiple 'as-value' properties defined (%s vs %s)",
209 _jsonValueAccessors.get(0),
210 _jsonValueAccessors.get(1));
211 }
212
213 return _jsonValueAccessors.get(0);
214 }
215 return null;
216 }
217
218 public AnnotatedMember getAnyGetter()
219 {
220 if (!_collected) {
221 collectAll();
222 }
223 if (_anyGetters != null) {
224 if (_anyGetters.size() > 1) {
225 reportProblem("Multiple 'any-getters' defined (%s vs %s)",
226 _anyGetters.get(0), _anyGetters.get(1));
227 }
228 return _anyGetters.getFirst();
229 }
230 return null;
231 }
232
233 public AnnotatedMember getAnySetterField()
234 {
235 if (!_collected) {
236 collectAll();
237 }
238 if (_anySetterField != null) {
239 if (_anySetterField.size() > 1) {
240 reportProblem("Multiple 'any-setter' fields defined (%s vs %s)",
241 _anySetterField.get(0), _anySetterField.get(1));
242 }
243 return _anySetterField.getFirst();
244 }
245 return null;
246 }
247
248 public AnnotatedMethod getAnySetterMethod()
249 {
250 if (!_collected) {
251 collectAll();
252 }
253 if (_anySetters != null) {
254 if (_anySetters.size() > 1) {
255 reportProblem("Multiple 'any-setter' methods defined (%s vs %s)",
256 _anySetters.get(0), _anySetters.get(1));
257 }
258 return _anySetters.getFirst();
259 }
260 return null;
261 }
262
263
267 public Set<String> getIgnoredPropertyNames() {
268 return _ignoredPropertyNames;
269 }
270
271
275 public ObjectIdInfo getObjectIdInfo()
276 {
277 ObjectIdInfo info = _annotationIntrospector.findObjectIdInfo(_classDef);
278 if (info != null) {
279 info = _annotationIntrospector.findObjectReferenceInfo(_classDef, info);
280 }
281 return info;
282 }
283
284
285 protected Map<String, POJOPropertyBuilder> getPropertyMap() {
286 if (!_collected) {
287 collectAll();
288 }
289 return _properties;
290 }
291
292 @Deprecated
293 public AnnotatedMethod getJsonValueMethod() {
294 AnnotatedMember m = getJsonValueAccessor();
295 if (m instanceof AnnotatedMethod) {
296 return (AnnotatedMethod) m;
297 }
298 return null;
299 }
300
301 @Deprecated
302 public Class<?> findPOJOBuilderClass() {
303 return _annotationIntrospector.findPOJOBuilder(_classDef);
304 }
305
306
311
312
317 protected void collectAll()
318 {
319 LinkedHashMap<String, POJOPropertyBuilder> props = new LinkedHashMap<String, POJOPropertyBuilder>();
320
321
322 _addFields(props);
323 _addMethods(props);
324
325
326 if (!_classDef.isNonStaticInnerClass()) {
327 _addCreators(props);
328 }
329
330
331
332 _removeUnwantedProperties(props);
333
334 _removeUnwantedAccessor(props);
335
336
337 _renameProperties(props);
338
339
340
341 _addInjectables(props);
342
343
344
345
346 for (POJOPropertyBuilder property : props.values()) {
347 property.mergeAnnotations(_forSerialization);
348 }
349
350
351 PropertyNamingStrategy naming = _findNamingStrategy();
352 if (naming != null) {
353 _renameUsing(props, naming);
354 }
355
356
357
358 for (POJOPropertyBuilder property : props.values()) {
359 property.trimByVisibility();
360 }
361
362
363
364 if (_config.isEnabled(MapperFeature.USE_WRAPPER_NAME_AS_PROPERTY_NAME)) {
365 _renameWithWrappers(props);
366 }
367
368
369 _sortProperties(props);
370 _properties = props;
371 _collected = true;
372 }
373
374
379
380
383 protected void _addFields(Map<String, POJOPropertyBuilder> props)
384 {
385 final AnnotationIntrospector ai = _annotationIntrospector;
386
390 final boolean pruneFinalFields = !_forSerialization && !_config.isEnabled(MapperFeature.ALLOW_FINAL_FIELDS_AS_MUTATORS);
391 final boolean transientAsIgnoral = _config.isEnabled(MapperFeature.PROPAGATE_TRANSIENT_MARKER);
392
393 for (AnnotatedField f : _classDef.fields()) {
394
395 if (Boolean.TRUE.equals(ai.hasAsValue(f))) {
396 if (_jsonValueAccessors == null) {
397 _jsonValueAccessors = new LinkedList<>();
398 }
399 _jsonValueAccessors.add(f);
400 continue;
401 }
402
403 if (Boolean.TRUE.equals(ai.hasAnySetter(f))) {
404 if (_anySetterField == null) {
405 _anySetterField = new LinkedList<AnnotatedMember>();
406 }
407 _anySetterField.add(f);
408 continue;
409 }
410 String implName = ai.findImplicitPropertyName(f);
411 if (implName == null) {
412 implName = f.getName();
413 }
414 final PropertyName implNameP = _propNameFromSimple(implName);
415
416
417
418
419 final PropertyName rename = ai.findRenameByField(_config, f, implNameP);
420 if ((rename != null) && !rename.equals(implNameP)) {
421 if (_fieldRenameMappings == null) {
422 _fieldRenameMappings = new HashMap<>();
423 }
424 _fieldRenameMappings.put(rename, implNameP);
425
426 }
427
428 PropertyName pn;
429
430 if (_forSerialization) {
431
432
433
434
435 pn = ai.findNameForSerialization(f);
436 } else {
437 pn = ai.findNameForDeserialization(f);
438 }
439 boolean hasName = (pn != null);
440 boolean nameExplicit = hasName;
441
442 if (nameExplicit && pn.isEmpty()) {
443 pn = _propNameFromSimple(implName);
444 nameExplicit = false;
445 }
446
447 boolean visible = (pn != null);
448 if (!visible) {
449 visible = _visibilityChecker.isFieldVisible(f);
450 }
451
452 boolean ignored = ai.hasIgnoreMarker(f);
453
454
455 if (f.isTransient()) {
456
457
458 if (!hasName) {
459 visible = false;
460 if (transientAsIgnoral) {
461 ignored = true;
462 }
463 }
464 }
465
470 if (pruneFinalFields && (pn == null) && !ignored
471 && Modifier.isFinal(f.getModifiers())) {
472 continue;
473 }
474 _property(props, implName).addField(f, pn, nameExplicit, visible, ignored);
475 }
476 }
477
478
481 protected void _addCreators(Map<String, POJOPropertyBuilder> props)
482 {
483
484 if (!_useAnnotations) {
485 return;
486 }
487 for (AnnotatedConstructor ctor : _classDef.getConstructors()) {
488 if (_creatorProperties == null) {
489 _creatorProperties = new LinkedList<POJOPropertyBuilder>();
490 }
491 for (int i = 0, len = ctor.getParameterCount(); i < len; ++i) {
492 _addCreatorParam(props, ctor.getParameter(i));
493 }
494 }
495 for (AnnotatedMethod factory : _classDef.getFactoryMethods()) {
496 if (_creatorProperties == null) {
497 _creatorProperties = new LinkedList<POJOPropertyBuilder>();
498 }
499 for (int i = 0, len = factory.getParameterCount(); i < len; ++i) {
500 _addCreatorParam(props, factory.getParameter(i));
501 }
502 }
503 }
504
505
508 protected void _addCreatorParam(Map<String, POJOPropertyBuilder> props,
509 AnnotatedParameter param)
510 {
511
512 String impl = _annotationIntrospector.findImplicitPropertyName(param);
513 if (impl == null) {
514 impl = "";
515 }
516 PropertyName pn = _annotationIntrospector.findNameForDeserialization(param);
517 boolean expl = (pn != null && !pn.isEmpty());
518 if (!expl) {
519 if (impl.isEmpty()) {
520
521
522 return;
523 }
524
525 JsonCreator.Mode creatorMode = _annotationIntrospector.findCreatorAnnotation(_config,
526 param.getOwner());
527 if ((creatorMode == null) || (creatorMode == JsonCreator.Mode.DISABLED)) {
528 return;
529 }
530 pn = PropertyName.construct(impl);
531 }
532
533
534 impl = _checkRenameByField(impl);
535
536
537
538
539
543 POJOPropertyBuilder prop = (expl && impl.isEmpty())
544 ? _property(props, pn) : _property(props, impl);
545 prop.addCtor(param, pn, expl, true, false);
546 _creatorProperties.add(prop);
547 }
548
549
552 protected void _addMethods(Map<String, POJOPropertyBuilder> props)
553 {
554 final AnnotationIntrospector ai = _annotationIntrospector;
555 for (AnnotatedMethod m : _classDef.memberMethods()) {
556
557
558
559
560
561 int argCount = m.getParameterCount();
562 if (argCount == 0) {
563 _addGetterMethod(props, m, ai);
564 } else if (argCount == 1) {
565 _addSetterMethod(props, m, ai);
566 } else if (argCount == 2) {
567 if (ai != null) {
568 if (Boolean.TRUE.equals(ai.hasAnySetter(m))) {
569 if (_anySetters == null) {
570 _anySetters = new LinkedList<AnnotatedMethod>();
571 }
572 _anySetters.add(m);
573 }
574 }
575 }
576 }
577 }
578
579 protected void _addGetterMethod(Map<String, POJOPropertyBuilder> props,
580 AnnotatedMethod m, AnnotationIntrospector ai)
581 {
582
583 if (!m.hasReturnType()) {
584 return;
585 }
586
587
588
589 if (Boolean.TRUE.equals(ai.hasAnyGetter(m))) {
590 if (_anyGetters == null) {
591 _anyGetters = new LinkedList<AnnotatedMember>();
592 }
593 _anyGetters.add(m);
594 return;
595 }
596
597 if (Boolean.TRUE.equals(ai.hasAsValue(m))) {
598 if (_jsonValueAccessors == null) {
599 _jsonValueAccessors = new LinkedList<>();
600 }
601 _jsonValueAccessors.add(m);
602 return;
603 }
604 String implName;
605 boolean visible;
606
607 PropertyName pn = ai.findNameForSerialization(m);
608 boolean nameExplicit = (pn != null);
609
610 if (!nameExplicit) {
611 implName = ai.findImplicitPropertyName(m);
612 if (implName == null) {
613 implName = BeanUtil.okNameForRegularGetter(m, m.getName(), _stdBeanNaming);
614 }
615 if (implName == null) {
616 implName = BeanUtil.okNameForIsGetter(m, m.getName(), _stdBeanNaming);
617 if (implName == null) {
618 return;
619 }
620 visible = _visibilityChecker.isIsGetterVisible(m);
621 } else {
622 visible = _visibilityChecker.isGetterVisible(m);
623 }
624 } else {
625
626 implName = ai.findImplicitPropertyName(m);
627 if (implName == null) {
628 implName = BeanUtil.okNameForGetter(m, _stdBeanNaming);
629 }
630
631 if (implName == null) {
632 implName = m.getName();
633 }
634 if (pn.isEmpty()) {
635
636 pn = _propNameFromSimple(implName);
637 nameExplicit = false;
638 }
639 visible = true;
640 }
641
642 implName = _checkRenameByField(implName);
643 boolean ignore = ai.hasIgnoreMarker(m);
644 _property(props, implName).addGetter(m, pn, nameExplicit, visible, ignore);
645 }
646
647 protected void _addSetterMethod(Map<String, POJOPropertyBuilder> props,
648 AnnotatedMethod m, AnnotationIntrospector ai)
649 {
650 String implName;
651 boolean visible;
652 PropertyName pn = (ai == null) ? null : ai.findNameForDeserialization(m);
653 boolean nameExplicit = (pn != null);
654 if (!nameExplicit) {
655 implName = (ai == null) ? null : ai.findImplicitPropertyName(m);
656 if (implName == null) {
657 implName = BeanUtil.okNameForMutator(m, _mutatorPrefix, _stdBeanNaming);
658 }
659 if (implName == null) {
660 return;
661 }
662 visible = _visibilityChecker.isSetterVisible(m);
663 } else {
664
665 implName = (ai == null) ? null : ai.findImplicitPropertyName(m);
666 if (implName == null) {
667 implName = BeanUtil.okNameForMutator(m, _mutatorPrefix, _stdBeanNaming);
668 }
669
670 if (implName == null) {
671 implName = m.getName();
672 }
673 if (pn.isEmpty()) {
674
675 pn = _propNameFromSimple(implName);
676 nameExplicit = false;
677 }
678 visible = true;
679 }
680
681 implName = _checkRenameByField(implName);
682 boolean ignore = (ai == null) ? false : ai.hasIgnoreMarker(m);
683 _property(props, implName).addSetter(m, pn, nameExplicit, visible, ignore);
684 }
685
686 protected void _addInjectables(Map<String, POJOPropertyBuilder> props)
687 {
688 final AnnotationIntrospector ai = _annotationIntrospector;
689
690 for (AnnotatedField f : _classDef.fields()) {
691 _doAddInjectable(ai.findInjectableValue(f), f);
692 }
693
694 for (AnnotatedMethod m : _classDef.memberMethods()) {
695
696 if (m.getParameterCount() != 1) {
697 continue;
698 }
699 _doAddInjectable(ai.findInjectableValue(m), m);
700 }
701 }
702
703 protected void _doAddInjectable(JacksonInject.Value injectable, AnnotatedMember m)
704 {
705 if (injectable == null) {
706 return;
707 }
708 Object id = injectable.getId();
709 if (_injectables == null) {
710 _injectables = new LinkedHashMap<Object, AnnotatedMember>();
711 }
712 AnnotatedMember prev = _injectables.put(id, m);
713 if (prev != null) {
714
715 if (prev.getClass() == m.getClass()) {
716 String type = id.getClass().getName();
717 throw new IllegalArgumentException("Duplicate injectable value with id '"
718 +String.valueOf(id)+"' (of type "+type+")");
719 }
720 }
721 }
722
723 private PropertyName _propNameFromSimple(String simpleName) {
724 return PropertyName.construct(simpleName, null);
725 }
726
727
728 private String _checkRenameByField(String implName) {
729 if (_fieldRenameMappings != null) {
730 PropertyName p = _fieldRenameMappings.get(_propNameFromSimple(implName));
731 if (p != null) {
732 implName = p.getSimpleName();
733 return implName;
734
735 }
736 }
737 return implName;
738 }
739
740
745
746
750 protected void _removeUnwantedProperties(Map<String, POJOPropertyBuilder> props)
751 {
752 Iterator<POJOPropertyBuilder> it = props.values().iterator();
753 while (it.hasNext()) {
754 POJOPropertyBuilder prop = it.next();
755
756
757 if (!prop.anyVisible()) {
758 it.remove();
759 continue;
760 }
761
762 if (prop.anyIgnorals()) {
763
764 if (!prop.isExplicitlyIncluded()) {
765 it.remove();
766 _collectIgnorals(prop.getName());
767 continue;
768 }
769
770 prop.removeIgnored();
771 if (!prop.couldDeserialize()) {
772 _collectIgnorals(prop.getName());
773 }
774 }
775 }
776 }
777
778
783 protected void _removeUnwantedAccessor(Map<String, POJOPropertyBuilder> props)
784 {
785 final boolean inferMutators = _config.isEnabled(MapperFeature.INFER_PROPERTY_MUTATORS);
786 Iterator<POJOPropertyBuilder> it = props.values().iterator();
787
788 while (it.hasNext()) {
789 POJOPropertyBuilder prop = it.next();
790
791 JsonProperty.Access acc = prop.removeNonVisible(inferMutators);
792 if (acc == JsonProperty.Access.READ_ONLY) {
793 _collectIgnorals(prop.getName());
794 }
795 }
796 }
797
798
803 private void _collectIgnorals(String name)
804 {
805 if (!_forSerialization) {
806 if (_ignoredPropertyNames == null) {
807 _ignoredPropertyNames = new HashSet<String>();
808 }
809 _ignoredPropertyNames.add(name);
810 }
811 }
812
813
818
819 protected void _renameProperties(Map<String, POJOPropertyBuilder> props)
820 {
821
822 Iterator<Map.Entry<String,POJOPropertyBuilder>> it = props.entrySet().iterator();
823 LinkedList<POJOPropertyBuilder> renamed = null;
824 while (it.hasNext()) {
825 Map.Entry<String, POJOPropertyBuilder> entry = it.next();
826 POJOPropertyBuilder prop = entry.getValue();
827
828 Collection<PropertyName> l = prop.findExplicitNames();
829
830
831 if (l.isEmpty()) {
832 continue;
833 }
834 it.remove();
835 if (renamed == null) {
836 renamed = new LinkedList<POJOPropertyBuilder>();
837 }
838
839 if (l.size() == 1) {
840 PropertyName n = l.iterator().next();
841 renamed.add(prop.withName(n));
842 continue;
843 }
844
845 renamed.addAll(prop.explode(l));
846
847
858 }
859
860
861 if (renamed != null) {
862 for (POJOPropertyBuilder prop : renamed) {
863 String name = prop.getName();
864 POJOPropertyBuilder old = props.get(name);
865 if (old == null) {
866 props.put(name, prop);
867 } else {
868 old.addAll(prop);
869 }
870
871 _updateCreatorProperty(prop, _creatorProperties);
872
873
874
875 if (_ignoredPropertyNames != null) {
876 _ignoredPropertyNames.remove(name);
877 }
878 }
879 }
880 }
881
882 protected void _renameUsing(Map<String, POJOPropertyBuilder> propMap,
883 PropertyNamingStrategy naming)
884 {
885 POJOPropertyBuilder[] props = propMap.values().toArray(new POJOPropertyBuilder[propMap.size()]);
886 propMap.clear();
887 for (POJOPropertyBuilder prop : props) {
888 PropertyName fullName = prop.getFullName();
889 String rename = null;
890
891
892 if (!prop.isExplicitlyNamed() || _config.isEnabled(MapperFeature.ALLOW_EXPLICIT_PROPERTY_RENAMING)) {
893 if (_forSerialization) {
894 if (prop.hasGetter()) {
895 rename = naming.nameForGetterMethod(_config, prop.getGetter(), fullName.getSimpleName());
896 } else if (prop.hasField()) {
897 rename = naming.nameForField(_config, prop.getField(), fullName.getSimpleName());
898 }
899 } else {
900 if (prop.hasSetter()) {
901 rename = naming.nameForSetterMethod(_config, prop.getSetter(), fullName.getSimpleName());
902 } else if (prop.hasConstructorParameter()) {
903 rename = naming.nameForConstructorParameter(_config, prop.getConstructorParameter(), fullName.getSimpleName());
904 } else if (prop.hasField()) {
905 rename = naming.nameForField(_config, prop.getField(), fullName.getSimpleName());
906 } else if (prop.hasGetter()) {
907
910 rename = naming.nameForGetterMethod(_config, prop.getGetter(), fullName.getSimpleName());
911 }
912 }
913 }
914 final String simpleName;
915 if ((rename != null) && !fullName.hasSimpleName(rename)) {
916 prop = prop.withSimpleName(rename);
917 simpleName = rename;
918 } else {
919 simpleName = fullName.getSimpleName();
920 }
921
922 POJOPropertyBuilder old = propMap.get(simpleName);
923 if (old == null) {
924 propMap.put(simpleName, prop);
925 } else {
926 old.addAll(prop);
927 }
928
929
930 _updateCreatorProperty(prop, _creatorProperties);
931 }
932 }
933
934 protected void _renameWithWrappers(Map<String, POJOPropertyBuilder> props)
935 {
936
937
938 Iterator<Map.Entry<String,POJOPropertyBuilder>> it = props.entrySet().iterator();
939 LinkedList<POJOPropertyBuilder> renamed = null;
940 while (it.hasNext()) {
941 Map.Entry<String, POJOPropertyBuilder> entry = it.next();
942 POJOPropertyBuilder prop = entry.getValue();
943 AnnotatedMember member = prop.getPrimaryMember();
944 if (member == null) {
945 continue;
946 }
947 PropertyName wrapperName = _annotationIntrospector.findWrapperName(member);
948
949
950
951 if (wrapperName == null || !wrapperName.hasSimpleName()) {
952 continue;
953 }
954 if (!wrapperName.equals(prop.getFullName())) {
955 if (renamed == null) {
956 renamed = new LinkedList<POJOPropertyBuilder>();
957 }
958 prop = prop.withName(wrapperName);
959 renamed.add(prop);
960 it.remove();
961 }
962 }
963
964 if (renamed != null) {
965 for (POJOPropertyBuilder prop : renamed) {
966 String name = prop.getName();
967 POJOPropertyBuilder old = props.get(name);
968 if (old == null) {
969 props.put(name, prop);
970 } else {
971 old.addAll(prop);
972 }
973 }
974 }
975 }
976
977
982
983
984
985
986
987 protected void _sortProperties(Map<String, POJOPropertyBuilder> props)
988 {
989
990 final AnnotationIntrospector intr = _annotationIntrospector;
991 Boolean alpha = intr.findSerializationSortAlphabetically((Annotated) _classDef);
992 final boolean sort = (alpha == null)
993 ? _config.shouldSortPropertiesAlphabetically()
994 : alpha.booleanValue();
995 final boolean indexed = _anyIndexed(props.values());
996
997 String[] propertyOrder = intr.findSerializationPropertyOrder(_classDef);
998
999
1000 if (!sort && !indexed && (_creatorProperties == null) && (propertyOrder == null)) {
1001 return;
1002 }
1003 int size = props.size();
1004 Map<String, POJOPropertyBuilder> all;
1005
1006 if (sort) {
1007 all = new TreeMap<String,POJOPropertyBuilder>();
1008 } else {
1009 all = new LinkedHashMap<String,POJOPropertyBuilder>(size+size);
1010 }
1011
1012 for (POJOPropertyBuilder prop : props.values()) {
1013 all.put(prop.getName(), prop);
1014 }
1015 Map<String,POJOPropertyBuilder> ordered = new LinkedHashMap<>(size+size);
1016
1017 if (propertyOrder != null) {
1018 for (String name : propertyOrder) {
1019 POJOPropertyBuilder w = all.remove(name);
1020 if (w == null) {
1021 for (POJOPropertyBuilder prop : props.values()) {
1022 if (name.equals(prop.getInternalName())) {
1023 w = prop;
1024
1025 name = prop.getName();
1026 break;
1027 }
1028 }
1029 }
1030 if (w != null) {
1031 ordered.put(name, w);
1032 }
1033 }
1034 }
1035
1036
1037 if (indexed) {
1038 Map<Integer,POJOPropertyBuilder> byIndex = new TreeMap<>();
1039 Iterator<Map.Entry<String,POJOPropertyBuilder>> it = all.entrySet().iterator();
1040 while (it.hasNext()) {
1041 Map.Entry<String,POJOPropertyBuilder> entry = it.next();
1042 POJOPropertyBuilder prop = entry.getValue();
1043 Integer index = prop.getMetadata().getIndex();
1044 if (index != null) {
1045 byIndex.put(index, prop);
1046 it.remove();
1047 }
1048 }
1049 for (POJOPropertyBuilder prop : byIndex.values()) {
1050 ordered.put(prop.getName(), prop);
1051 }
1052 }
1053
1054
1055 if (_creatorProperties != null) {
1056
1061 Collection<POJOPropertyBuilder> cr;
1062 if (sort) {
1063 TreeMap<String, POJOPropertyBuilder> sorted =
1064 new TreeMap<String,POJOPropertyBuilder>();
1065 for (POJOPropertyBuilder prop : _creatorProperties) {
1066 sorted.put(prop.getName(), prop);
1067 }
1068 cr = sorted.values();
1069 } else {
1070 cr = _creatorProperties;
1071 }
1072 for (POJOPropertyBuilder prop : cr) {
1073
1074
1075 String name = prop.getName();
1076
1077
1078 if (all.containsKey(name)) {
1079 ordered.put(name, prop);
1080 }
1081 }
1082 }
1083
1084 ordered.putAll(all);
1085 props.clear();
1086 props.putAll(ordered);
1087 }
1088
1089 private boolean _anyIndexed(Collection<POJOPropertyBuilder> props) {
1090 for (POJOPropertyBuilder prop : props) {
1091 if (prop.getMetadata().hasIndex()) {
1092 return true;
1093 }
1094 }
1095 return false;
1096 }
1097
1098
1103
1104 protected void reportProblem(String msg, Object... args) {
1105 if (args.length > 0) {
1106 msg = String.format(msg, args);
1107 }
1108 throw new IllegalArgumentException("Problem with definition of "+_classDef+": "+msg);
1109 }
1110
1111 protected POJOPropertyBuilder _property(Map<String, POJOPropertyBuilder> props,
1112 PropertyName name) {
1113 String simpleName = name.getSimpleName();
1114 POJOPropertyBuilder prop = props.get(simpleName);
1115 if (prop == null) {
1116 prop = new POJOPropertyBuilder(_config, _annotationIntrospector,
1117 _forSerialization, name);
1118 props.put(simpleName, prop);
1119 }
1120 return prop;
1121 }
1122
1123
1124 protected POJOPropertyBuilder _property(Map<String, POJOPropertyBuilder> props,
1125 String implName)
1126 {
1127 POJOPropertyBuilder prop = props.get(implName);
1128 if (prop == null) {
1129 prop = new POJOPropertyBuilder(_config, _annotationIntrospector, _forSerialization,
1130 PropertyName.construct(implName));
1131 props.put(implName, prop);
1132 }
1133 return prop;
1134 }
1135
1136 private PropertyNamingStrategy _findNamingStrategy()
1137 {
1138 Object namingDef = _annotationIntrospector.findNamingStrategy(_classDef);
1139 if (namingDef == null) {
1140 return _config.getPropertyNamingStrategy();
1141 }
1142 if (namingDef instanceof PropertyNamingStrategy) {
1143 return (PropertyNamingStrategy) namingDef;
1144 }
1145
1148 if (!(namingDef instanceof Class)) {
1149 throw new IllegalStateException("AnnotationIntrospector returned PropertyNamingStrategy definition of type "
1150 +namingDef.getClass().getName()+"; expected type PropertyNamingStrategy or Class<PropertyNamingStrategy> instead");
1151 }
1152 Class<?> namingClass = (Class<?>)namingDef;
1153
1154 if (namingClass == PropertyNamingStrategy.class) {
1155 return null;
1156 }
1157
1158 if (!PropertyNamingStrategy.class.isAssignableFrom(namingClass)) {
1159 throw new IllegalStateException("AnnotationIntrospector returned Class "
1160 +namingClass.getName()+"; expected Class<PropertyNamingStrategy>");
1161 }
1162 HandlerInstantiator hi = _config.getHandlerInstantiator();
1163 if (hi != null) {
1164 PropertyNamingStrategy pns = hi.namingStrategyInstance(_config, _classDef, namingClass);
1165 if (pns != null) {
1166 return pns;
1167 }
1168 }
1169 return (PropertyNamingStrategy) ClassUtil.createInstance(namingClass,
1170 _config.canOverrideAccessModifiers());
1171 }
1172
1173 protected void _updateCreatorProperty(POJOPropertyBuilder prop, List<POJOPropertyBuilder> creatorProperties) {
1174
1175 if (creatorProperties != null) {
1176 final String intName = prop.getInternalName();
1177 for (int i = 0, len = creatorProperties.size(); i < len; ++i) {
1178 if (creatorProperties.get(i).getInternalName().equals(intName)) {
1179 creatorProperties.set(i, prop);
1180 break;
1181 }
1182 }
1183 }
1184 }
1185 }
1186