• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 package com.fasterxml.jackson.databind.cfg;
2 
3 import java.security.AccessController;
4 import java.security.PrivilegedAction;
5 import java.text.DateFormat;
6 import java.util.*;
7 
8 import com.fasterxml.jackson.annotation.JsonAutoDetect;
9 import com.fasterxml.jackson.annotation.JsonInclude;
10 import com.fasterxml.jackson.annotation.JsonSetter;
11 import com.fasterxml.jackson.annotation.JsonTypeInfo;
12 import com.fasterxml.jackson.annotation.PropertyAccessor;
13 import com.fasterxml.jackson.core.*;
14 import com.fasterxml.jackson.databind.*;
15 import com.fasterxml.jackson.databind.ObjectMapper.DefaultTyping;
16 import com.fasterxml.jackson.databind.deser.*;
17 import com.fasterxml.jackson.databind.introspect.VisibilityChecker;
18 import com.fasterxml.jackson.databind.jsontype.NamedType;
19 import com.fasterxml.jackson.databind.jsontype.PolymorphicTypeValidator;
20 import com.fasterxml.jackson.databind.jsontype.SubtypeResolver;
21 import com.fasterxml.jackson.databind.jsontype.TypeResolverBuilder;
22 import com.fasterxml.jackson.databind.node.JsonNodeFactory;
23 import com.fasterxml.jackson.databind.ser.*;
24 import com.fasterxml.jackson.databind.type.TypeFactory;
25 
26 /**
27  * Jackson 3 will introduce fully immutable, builder-based system for constructing
28  * {@link ObjectMapper}s. Same can not be done with 2.10 for backwards-compatibility
29  * reasons; but we can offer sort of "fake" builder, which simply encapsulates
30  * configuration calls. The main (and only) point is to allow gradual upgrade.
31  *
32  * @since 2.10
33  */
34 public abstract class MapperBuilder<M extends ObjectMapper,
35     B extends MapperBuilder<M,B>>
36 {
37     protected final M _mapper;
38 
39     /*
40     /**********************************************************************
41     /* Life-cycle
42     /**********************************************************************
43      */
44 
MapperBuilder(M mapper)45     protected MapperBuilder(M mapper)
46     {
47         _mapper = mapper;
48     }
49 
50     /**
51      * Method to call to create actual mapper instance.
52      *<p>
53      * Implementation detail: in 2.10 (but not 3.x) underlying mapper is eagerly
54      * constructed when builder is constructed, and method simply returns that
55      * instance.
56      */
build()57     public M build() {
58         return _mapper;
59     }
60 
61     /*
62     /**********************************************************************
63     /* Accessors, features
64     /**********************************************************************
65      */
66 
isEnabled(MapperFeature f)67     public boolean isEnabled(MapperFeature f) {
68         return _mapper.isEnabled(f);
69     }
isEnabled(DeserializationFeature f)70     public boolean isEnabled(DeserializationFeature f) {
71         return _mapper.isEnabled(f);
72     }
isEnabled(SerializationFeature f)73     public boolean isEnabled(SerializationFeature f) {
74         return _mapper.isEnabled(f);
75     }
76 
isEnabled(JsonParser.Feature f)77     public boolean isEnabled(JsonParser.Feature f) {
78         return _mapper.isEnabled(f);
79     }
isEnabled(JsonGenerator.Feature f)80     public boolean isEnabled(JsonGenerator.Feature f) {
81         return _mapper.isEnabled(f);
82     }
83 
84     /*
85     /**********************************************************************
86     /* Accessors, other
87     /**********************************************************************
88      */
89 
streamFactory()90     public TokenStreamFactory streamFactory() {
91         return _mapper.tokenStreamFactory();
92     }
93 
94     /*
95     /**********************************************************************
96     /* Changing features: mapper, ser, deser
97     /**********************************************************************
98      */
99 
enable(MapperFeature... features)100     public B enable(MapperFeature... features) {
101         _mapper.enable(features);
102         return _this();
103     }
104 
disable(MapperFeature... features)105     public B disable(MapperFeature... features) {
106         _mapper.disable(features);
107         return _this();
108     }
109 
configure(MapperFeature feature, boolean state)110     public B configure(MapperFeature feature, boolean state) {
111         _mapper.configure(feature, state);
112         return _this();
113     }
114 
enable(SerializationFeature... features)115     public B enable(SerializationFeature... features) {
116         for (SerializationFeature f : features) {
117             _mapper.enable(f);
118         }
119         return _this();
120     }
121 
disable(SerializationFeature... features)122     public B disable(SerializationFeature... features) {
123         for (SerializationFeature f : features) {
124             _mapper.disable(f);
125         }
126         return _this();
127     }
128 
configure(SerializationFeature feature, boolean state)129     public B configure(SerializationFeature feature, boolean state) {
130         _mapper.configure(feature, state);
131         return _this();
132     }
133 
enable(DeserializationFeature... features)134     public B enable(DeserializationFeature... features) {
135         for (DeserializationFeature f : features) {
136             _mapper.enable(f);
137         }
138         return _this();
139     }
140 
disable(DeserializationFeature... features)141     public B disable(DeserializationFeature... features) {
142         for (DeserializationFeature f : features) {
143             _mapper.disable(f);
144         }
145         return _this();
146     }
147 
configure(DeserializationFeature feature, boolean state)148     public B configure(DeserializationFeature feature, boolean state) {
149         _mapper.configure(feature, state);
150         return _this();
151     }
152 
153     /*
154     /**********************************************************************
155     /* Changing features: parser, generator, pre-2.10
156     /**********************************************************************
157      */
158 
enable(JsonParser.Feature... features)159     public B enable(JsonParser.Feature... features) {
160         _mapper.enable(features);
161         return _this();
162     }
163 
disable(JsonParser.Feature... features)164     public B disable(JsonParser.Feature... features) {
165         _mapper.disable(features);
166         return _this();
167     }
168 
configure(JsonParser.Feature feature, boolean state)169     public B configure(JsonParser.Feature feature, boolean state) {
170         _mapper.configure(feature, state);
171         return _this();
172     }
173 
enable(JsonGenerator.Feature... features)174     public B enable(JsonGenerator.Feature... features) {
175         _mapper.enable(features);
176         return _this();
177     }
178 
disable(JsonGenerator.Feature... features)179     public B disable(JsonGenerator.Feature... features) {
180         _mapper.disable(features);
181         return _this();
182     }
183 
configure(JsonGenerator.Feature feature, boolean state)184     public B configure(JsonGenerator.Feature feature, boolean state) {
185         _mapper.configure(feature, state);
186         return _this();
187     }
188 
189     /*
190     /**********************************************************************
191     /* Changing features: parser, generator, 2.10+
192     /**********************************************************************
193      */
194 
enable(StreamReadFeature... features)195     public B enable(StreamReadFeature... features) {
196         for (StreamReadFeature f : features) {
197             _mapper.enable(f.mappedFeature());
198         }
199         return _this();
200     }
201 
disable(StreamReadFeature... features)202     public B disable(StreamReadFeature... features) {
203         for (StreamReadFeature f : features) {
204             _mapper.disable(f.mappedFeature());
205         }
206         return _this();
207     }
208 
configure(StreamReadFeature feature, boolean state)209     public B configure(StreamReadFeature feature, boolean state) {
210         _mapper.configure(feature.mappedFeature(), state);
211         return _this();
212     }
213 
enable(StreamWriteFeature... features)214     public B enable(StreamWriteFeature... features) {
215         for (StreamWriteFeature f : features) {
216             _mapper.enable(f.mappedFeature());
217         }
218         return _this();
219     }
220 
disable(StreamWriteFeature... features)221     public B disable(StreamWriteFeature... features) {
222         for (StreamWriteFeature f : features) {
223             _mapper.disable(f.mappedFeature());
224         }
225         return _this();
226     }
227 
configure(StreamWriteFeature feature, boolean state)228     public B configure(StreamWriteFeature feature, boolean state) {
229         _mapper.configure(feature.mappedFeature(), state);
230         return _this();
231     }
232 
233     /*
234     /**********************************************************************
235     /* Module registration, discovery, access
236     /**********************************************************************
237      */
238 
addModule(com.fasterxml.jackson.databind.Module module)239     public B addModule(com.fasterxml.jackson.databind.Module module)
240     {
241         _mapper.registerModule(module);
242         return _this();
243     }
244 
addModules(com.fasterxml.jackson.databind.Module... modules)245     public B addModules(com.fasterxml.jackson.databind.Module... modules)
246     {
247         for (com.fasterxml.jackson.databind.Module module : modules) {
248             addModule(module);
249         }
250         return _this();
251     }
252 
addModules(Iterable<? extends com.fasterxml.jackson.databind.Module> modules)253     public B addModules(Iterable<? extends com.fasterxml.jackson.databind.Module> modules)
254     {
255         for (com.fasterxml.jackson.databind.Module module : modules) {
256             addModule(module);
257         }
258         return _this();
259     }
260 
261     /**
262      * Method for locating available methods, using JDK {@link ServiceLoader}
263      * facility, along with module-provided SPI.
264      *<p>
265      * Note that method does not do any caching, so calls should be considered
266      * potentially expensive.
267      */
findModules()268     public static List<com.fasterxml.jackson.databind.Module> findModules() {
269         return findModules(null);
270     }
271 
272     /**
273      * Method for locating available methods, using JDK {@link ServiceLoader}
274      * facility, along with module-provided SPI.
275      *<p>
276      * Note that method does not do any caching, so calls should be considered
277      * potentially expensive.
278      */
findModules(ClassLoader classLoader)279     public static List<com.fasterxml.jackson.databind.Module> findModules(ClassLoader classLoader)
280     {
281         ArrayList<com.fasterxml.jackson.databind.Module> modules = new ArrayList<>();
282         ServiceLoader<com.fasterxml.jackson.databind.Module> loader = secureGetServiceLoader(com.fasterxml.jackson.databind.Module.class, classLoader);
283         for (com.fasterxml.jackson.databind.Module module : loader) {
284             modules.add(module);
285         }
286         return modules;
287     }
288 
secureGetServiceLoader(final Class<T> clazz, final ClassLoader classLoader)289     private static <T> ServiceLoader<T> secureGetServiceLoader(final Class<T> clazz, final ClassLoader classLoader) {
290         final SecurityManager sm = System.getSecurityManager();
291         if (sm == null) {
292             return (classLoader == null) ?
293                     ServiceLoader.load(clazz) : ServiceLoader.load(clazz, classLoader);
294         }
295         return AccessController.doPrivileged(new PrivilegedAction<ServiceLoader<T>>() {
296             @Override
297             public ServiceLoader<T> run() {
298                 return (classLoader == null) ?
299                         ServiceLoader.load(clazz) : ServiceLoader.load(clazz, classLoader);
300             }
301         });
302     }
303 
304     /**
305      * Convenience method that is functionally equivalent to:
306      *<code>
307      *   addModules(builder.findModules());
308      *</code>
309      *<p>
310      * As with {@link #findModules()}, no caching is done for modules, so care
311      * needs to be taken to either create and share a single mapper instance;
312      * or to cache introspected set of modules.
313      */
314     public B findAndAddModules() {
315         return addModules(findModules());
316     }
317 
318     /*
319     /**********************************************************************
320     /* Changing base settings
321     /**********************************************************************
322      */
323 
324     /**
325      * Method for replacing {@link AnnotationIntrospector} used by the
326      * mapper instance to be built.
327      * Note that doing this will replace the current introspector, which
328      * may lead to unavailability of core Jackson annotations.
329      * If you want to combine handling of multiple introspectors,
330      * have a look at {@link com.fasterxml.jackson.databind.introspect.AnnotationIntrospectorPair}.
331      *
332      * @see com.fasterxml.jackson.databind.introspect.AnnotationIntrospectorPair
333      */
334     public B annotationIntrospector(AnnotationIntrospector intr) {
335         _mapper.setAnnotationIntrospector(intr);
336         return _this();
337     }
338 
339     public B nodeFactory(JsonNodeFactory f) {
340         _mapper.setNodeFactory(f);
341         return _this();
342     }
343 
344     /*
345     /**********************************************************************
346     /* Changing introspection helpers
347     /**********************************************************************
348      */
349 
350     public B typeFactory(TypeFactory f) {
351         _mapper.setTypeFactory(f);
352         return _this();
353     }
354 
355     public B subtypeResolver(SubtypeResolver r) {
356         _mapper.setSubtypeResolver(r);
357         return _this();
358     }
359 
360     public B visibility(VisibilityChecker<?> vc) {
361         _mapper.setVisibility(vc);
362         return _this();
363     }
364 
365     public B visibility(PropertyAccessor forMethod, JsonAutoDetect.Visibility visibility) {
366         _mapper.setVisibility(forMethod, visibility);
367         return _this();
368     }
369 
370     /**
371      * Method for configuring {@link HandlerInstantiator} to use for creating
372      * instances of handlers (such as serializers, deserializers, type and type
373      * id resolvers), given a class.
374      *
375      * @param hi Instantiator to use; if null, use the default implementation
376      */
377     public B handlerInstantiator(HandlerInstantiator hi) {
378         _mapper.setHandlerInstantiator(hi);
379         return _this();
380     }
381 
382     public B propertyNamingStrategy(PropertyNamingStrategy s) {
383         _mapper.setPropertyNamingStrategy(s);
384         return _this();
385     }
386 
387     /*
388     /**********************************************************************
389     /* Changing factories, serialization
390     /**********************************************************************
391      */
392 
393     public B serializerFactory(SerializerFactory f) {
394         _mapper.setSerializerFactory(f);
395         return _this();
396     }
397 
398     /**
399      * Method for configuring this mapper to use specified {@link FilterProvider} for
400      * mapping Filter Ids to actual filter instances.
401      *<p>
402      * Note that usually it is better to use method in {@link ObjectWriter}, but sometimes
403      * this method is more convenient. For example, some frameworks only allow configuring
404      * of ObjectMapper instances and not {@link ObjectWriter}s.
405      */
406     public B filterProvider(FilterProvider prov) {
407         _mapper.setFilterProvider(prov);
408         return _this();
409     }
410 
411     public B defaultPrettyPrinter(PrettyPrinter pp) {
412         _mapper.setDefaultPrettyPrinter(pp);
413         return _this();
414     }
415 
416     /*
417     /**********************************************************************
418     /* Changing factories, related, deserialization
419     /**********************************************************************
420      */
421 
422     public B injectableValues(InjectableValues v) {
423         _mapper.setInjectableValues(v);
424         return _this();
425     }
426 
427     /**
428      * Method used for adding a {@link DeserializationProblemHandler} for this
429      * builder, at the head of the list (meaning it has priority over handler
430      * registered earlier).
431      */
432     public B addHandler(DeserializationProblemHandler h) {
433         _mapper.addHandler(h);
434         return _this();
435     }
436 
437     /**
438      * Method that may be used to remove all {@link DeserializationProblemHandler}s added
439      * to this builder (if any).
440      */
441     public B clearProblemHandlers() {
442         _mapper.clearProblemHandlers();
443         return _this();
444     }
445 
446     /*
447     /**********************************************************************
448     /* Changing global defaults
449     /**********************************************************************
450      */
451 
452     public B defaultSetterInfo(JsonSetter.Value v) {
453         _mapper.setDefaultSetterInfo(v);
454         return _this();
455     }
456 
457     /**
458      * Method for setting default Setter configuration, regarding things like
459      * merging, null-handling; used for properties for which there are
460      * no per-type or per-property overrides (via annotations or config overrides).
461      */
462     public B defaultMergeable(Boolean b) {
463         _mapper.setDefaultMergeable(b);
464         return _this();
465     }
466 
467     /**
468      * Method for setting default Setter configuration, regarding things like
469      * merging, null-handling; used for properties for which there are
470      * no per-type or per-property overrides (via annotations or config overrides).
471      */
472     public B defaultLeniency(Boolean b) {
473         _mapper.setDefaultLeniency(b);
474         return _this();
475     }
476 
477     /*
478     /**********************************************************************
479     /* Changing settings, date/time
480     /**********************************************************************
481      */
482 
483     /**
484      * Method for configuring the default {@link DateFormat} to use when serializing time
485      * values as Strings, and deserializing from JSON Strings.
486      * If you need per-request configuration, factory methods in
487      * {@link ObjectReader} and {@link ObjectWriter} instead.
488      */
489     public B defaultDateFormat(DateFormat df) {
490         _mapper.setDateFormat(df);
491         return _this();
492     }
493 
494     /**
495      * Method for overriding default TimeZone to use for formatting.
496      * Default value used is UTC (NOT default TimeZone of JVM).
497      */
498     public B defaultTimeZone(TimeZone tz) {
499         _mapper.setTimeZone(tz);
500         return _this();
501     }
502 
503     /**
504      * Method for overriding default locale to use for formatting.
505      * Default value used is {@link Locale#getDefault()}.
506      */
507     public B defaultLocale(Locale locale) {
508         _mapper.setLocale(locale);
509         return _this();
510     }
511 
512     /*
513     /**********************************************************************
514     /* Changing settings, formatting
515     /**********************************************************************
516      */
517 
518     /**
519      * Method that will configure default {@link Base64Variant} that
520      * <code>byte[]</code> serializers and deserializers will use.
521      *
522      * @param v Base64 variant to use
523      *
524      * @return This builder instance to allow call chaining
525      */
526     public B defaultBase64Variant(Base64Variant v) {
527         _mapper.setBase64Variant(v);
528         return _this();
529     }
530 
531     /**
532      * Method for configured default property inclusion to use for serialization.
533      *
534      * @param incl Default property inclusion to set
535      *
536      * @return This builder instance to allow call chaining
537      */
538     public B serializationInclusion(JsonInclude.Include incl) {
539         _mapper.setSerializationInclusion(incl);
540         return _this();
541     }
542 
543     /**
544      * Method for configured default property inclusion to use for serialization.
545      *
546      * @param incl Default property inclusion to set
547      *
548      * @return This builder instance to allow call chaining
549      *
550      * @since 2.11
551      */
552     public B defaultPropertyInclusion(JsonInclude.Value incl) {
553         _mapper.setDefaultPropertyInclusion(incl);
554         return _this();
555     }
556 
557     /*
558     /**********************************************************************
559     /* Adding Mix-ins
560     /**********************************************************************
561      */
562 
563     /**
564      * Method to use for defining mix-in annotations to use for augmenting
565      * annotations that classes have, for purpose of configuration serialization
566      * and/or deserialization processing.
567      * Mixing in is done when introspecting class annotations and properties.
568      * Annotations from "mixin" class (and its supertypes)
569      * will <b>override</b>
570      * annotations that target classes (and their super-types) have.
571      *<p>
572      * Note that standard mixin handler implementations will only allow a single mix-in
573      * source class per target, so if there was a previous mix-in defined target it will
574      * be cleared. This also means that you can remove mix-in definition by specifying
575      * {@code mixinSource} of {@code null}
576      */
577     public B addMixIn(Class<?> target, Class<?> mixinSource)
578     {
579         _mapper.addMixIn(target, mixinSource);
580         return _this();
581     }
582 
583     /*
584     /**********************************************************************
585     /* Subtype registration, related
586     /**********************************************************************
587      */
588 
589     public B registerSubtypes(Class<?>... subtypes) {
590         _mapper.registerSubtypes(subtypes);
591         return _this();
592     }
593 
594     public B registerSubtypes(NamedType... subtypes) {
595         _mapper.registerSubtypes(subtypes);
596         return _this();
597     }
598 
599     public B registerSubtypes(Collection<Class<?>> subtypes) {
600         _mapper.registerSubtypes(subtypes);
601         return _this();
602     }
603 
604     /**
605      * Method for assigning {@link PolymorphicTypeValidator} to use for validating
606      * subtypes when using Class name - based polymorphic deserialization
607      * using annotations (validator used with "Default Typing" is specified by
608      * passing in {@link #activateDefaultTyping(PolymorphicTypeValidator)} instead).
609      *<p>
610      * Validator will be called on validating types for which no default databind
611      * deserializer, or module-provided deserializer is found: typically this
612      * includes "POJO" (aka Bean) types, but not (for example) most container
613      * types.
614      *
615      * @since 2.10
616      */
617     public B polymorphicTypeValidator(PolymorphicTypeValidator ptv) {
618         _mapper.setPolymorphicTypeValidator(ptv);
619         return _this();
620     }
621 
622     /*
623     /**********************************************************************
624     /* Default typing
625     /**********************************************************************
626      */
627 
628     /**
629      * Convenience method that is equivalent to calling
630      *<pre>
631      *  activateDefaultTyping(subtypeValidator, DefaultTyping.OBJECT_AND_NON_CONCRETE);
632      *</pre>
633      *<p>
634      * NOTE: choice of {@link PolymorphicTypeValidator} to pass is critical for security
635      * as allowing all subtypes can be risky for untrusted content.
636      */
637     public B activateDefaultTyping(PolymorphicTypeValidator subtypeValidator) {
638         _mapper.activateDefaultTyping(subtypeValidator);
639         return _this();
640     }
641 
642     /**
643      * Convenience method that is equivalent to calling
644      *<pre>
645      *  activateDefaultTyping(subtypeValidator, dti, JsonTypeInfo.As.WRAPPER_ARRAY);
646      *</pre>
647      *<p>
648      * NOTE: choice of {@link PolymorphicTypeValidator} to pass is critical for security
649      * as allowing all subtypes can be risky for untrusted content.
650      */
651     public B activateDefaultTyping(PolymorphicTypeValidator subtypeValidator,
652             DefaultTyping dti) {
653         _mapper.activateDefaultTyping(subtypeValidator, dti);
654         return _this();
655     }
656 
657     /**
658      * Method for enabling automatic inclusion of type information, needed
659      * for proper deserialization of polymorphic types (unless types
660      * have been annotated with {@link com.fasterxml.jackson.annotation.JsonTypeInfo}).
661      *<P>
662      * NOTE: use of <code>JsonTypeInfo.As#EXTERNAL_PROPERTY</code> <b>NOT SUPPORTED</b>;
663      * and attempts of do so will throw an {@link IllegalArgumentException} to make
664      * this limitation explicit.
665      *<p>
666      * NOTE: choice of {@link PolymorphicTypeValidator} to pass is critical for security
667      * as allowing all subtypes can be risky for untrusted content.
668      *
669      * @param applicability Defines kinds of types for which additional type information
670      *    is added; see {@link DefaultTyping} for more information.
671      */
672     public B activateDefaultTyping(PolymorphicTypeValidator subtypeValidator,
673             DefaultTyping applicability, JsonTypeInfo.As includeAs)
674     {
675         _mapper.activateDefaultTyping(subtypeValidator, applicability, includeAs);
676         return _this();
677     }
678 
679     /**
680      * Method for enabling automatic inclusion of type information -- needed
681      * for proper deserialization of polymorphic types (unless types
682      * have been annotated with {@link com.fasterxml.jackson.annotation.JsonTypeInfo}) --
683      * using "As.PROPERTY" inclusion mechanism and specified property name
684      * to use for inclusion (default being "@class" since default type information
685      * always uses class name as type identifier)
686      *<p>
687      * NOTE: choice of {@link PolymorphicTypeValidator} to pass is critical for security
688      * as allowing all subtypes can be risky for untrusted content.
689      */
690     public B activateDefaultTypingAsProperty(PolymorphicTypeValidator subtypeValidator,
691             DefaultTyping applicability, String propertyName)
692     {
693         _mapper.activateDefaultTypingAsProperty(subtypeValidator, applicability, propertyName);
694         return _this();
695     }
696 
697     /**
698      * Method for disabling automatic inclusion of type information; if so, only
699      * explicitly annotated types (ones with
700      * {@link com.fasterxml.jackson.annotation.JsonTypeInfo}) will have
701      * additional embedded type information.
702      */
703     public B deactivateDefaultTyping() {
704         _mapper.deactivateDefaultTyping();
705         return _this();
706     }
707 
708     /**
709      * Method for enabling automatic inclusion of type information, using
710      * specified handler object for determining which types this affects,
711      * as well as details of how information is embedded.
712      *<p>
713      * NOTE: use of Default Typing can be a potential security risk if incoming
714      * content comes from untrusted sources, so care should be taken to use
715      * a {@link TypeResolverBuilder} that can limit allowed classes to
716      * deserialize. Note in particular that
717      * {@link com.fasterxml.jackson.databind.jsontype.impl.StdTypeResolverBuilder}
718      * DOES NOT limit applicability but creates type (de)serializers for all
719      * types.
720      *
721      * @param typer Type information inclusion handler
722      *
723      * @since 2.12
724      */
725     public B setDefaultTyping(TypeResolverBuilder<?> typer) {
726         _mapper.setDefaultTyping(typer);
727         return _this();
728     }
729 
730     /*
731     /**********************************************************************
732     /* Other helper methods
733     /**********************************************************************
734      */
735 
736     // silly convenience cast method we need
737     @SuppressWarnings("unchecked")
738     protected final B _this() { return (B) this; }
739 }
740