aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/com/fasterxml/jackson/databind/BeanProperty.java
blob: e8a562c3f9396427e21069ae54e8fb9efa36d629 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
package com.fasterxml.jackson.databind;

import java.lang.annotation.Annotation;
import java.util.Collections;
import java.util.List;

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

import com.fasterxml.jackson.databind.cfg.MapperConfig;
import com.fasterxml.jackson.databind.introspect.AnnotatedMember;
import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonObjectFormatVisitor;
import com.fasterxml.jackson.databind.type.TypeFactory;
import com.fasterxml.jackson.databind.util.Annotations;
import com.fasterxml.jackson.databind.util.Named;

/**
 * Bean properties are logical entities that represent data
 * that Java objects (POJOs (Plain Old Java Objects), sometimes also called "beans")
 * contain; and that are accessed using accessors (methods like getters
 * and setters, fields, constructor parameters).
 * Instances allow access to annotations directly associated
 * to property (via field or method), as well as contextual
 * annotations (annotations for class that contains properties).
 *<p>
 * Instances are not typically passed when constructing serializers
 * and deserializers, but rather only passed when context
 * is known when
 * {@link com.fasterxml.jackson.databind.ser.ContextualSerializer} and
 * {@link com.fasterxml.jackson.databind.deser.ContextualDeserializer}
 * resolution occurs (<code>createContextual(...)</code> method is called).
 * References may (need to) be retained by serializers and deserializers,
 * especially when further resolving dependent handlers like value
 * serializers/deserializers or structured types.
 */
public interface BeanProperty extends Named
{
    public final static JsonFormat.Value EMPTY_FORMAT = new JsonFormat.Value();
    public final static JsonInclude.Value EMPTY_INCLUDE = JsonInclude.Value.empty();

    /**
     * Method to get logical name of the property
     */
    @Override
    public String getName();

    /**
     * Method for getting full name definition, including possible
     * format-specific additional properties (such as namespace when
     * using XML backend).
     * 
     * @since 2.3
     */
    public PropertyName getFullName();

    /**
     * Method to get declared type of the property.
     */
    public JavaType getType();

    /**
     * If property is indicated to be wrapped, name of
     * wrapper element to use.
     * 
     * @since 2.2
     */
    public PropertyName getWrapperName();

    /**
     * Accessor for additional optional information about property.
     * 
     * @since 2.3
     * 
     * @return Metadata about property; never null.
     */
    public PropertyMetadata getMetadata();
    
    /**
     * Whether value for property is marked as required using
     * annotations or associated schema.
     * Equivalent to:
     *<code>
     *  getMetadata().isRequired()
     *</code>
     * 
     * @since 2.2
     */
    public boolean isRequired();

    /**
     * Accessor for checking whether there is an actual physical property
     * behind this property abstraction or not.
     * 
     * @since 2.7
     */
    public boolean isVirtual();

    /*
    /**********************************************************
    /* Access to annotation information
    /**********************************************************
     */
    
    /**
     * Method for finding annotation associated with this property;
     * meaning annotation associated with one of entities used to
     * access property.
     *<p>
     * Note that this method should only be called for custom annotations;
     * access to standard Jackson annotations (or ones supported by
     * alternate {@link AnnotationIntrospector}s) should be accessed
     * through {@link AnnotationIntrospector}.
     */
    public <A extends Annotation> A getAnnotation(Class<A> acls);

    /**
     * Method for finding annotation associated with context of
     * this property; usually class in which member is declared
     * (or its subtype if processing subtype).
     *<p>
     * Note that this method should only be called for custom annotations;
     * access to standard Jackson annotations (or ones supported by
     * alternate {@link AnnotationIntrospector}s) should be accessed
     * through {@link AnnotationIntrospector}.
     */
    public <A extends Annotation> A getContextAnnotation(Class<A> acls);

    /**
     * Method for accessing primary physical entity that represents the property;
     * annotated field, method or constructor property.
     */
    public AnnotatedMember getMember();

    /**
     * Convenience method that is roughly equivalent to
     *<pre>
     *   return intr.findFormat(getMember());
     *</pre>
     * and specifically does NOT try to find per-type format defaults to merge;
     * use {@link #findPropertyFormat} if such defaults would be useful.
     *
     * @since 2.6
     * 
     * @deprecated since 2.8 use {@link #findPropertyFormat} instead.
     */
    @Deprecated
    public JsonFormat.Value findFormatOverrides(AnnotationIntrospector intr);

    /**
     * Helper method used to look up format settings applicable to this property,
     * considering both possible per-type configuration settings
     *
     * @since 2.7
     */
    public JsonFormat.Value findPropertyFormat(MapperConfig<?> config, Class<?> baseType);
    
    /**
     * Convenience method that is roughly equivalent to
     *<pre>
     *   return config.getAnnotationIntrospector().findPropertyInclusion(getMember());
     *</pre>
     * but also considers global default settings for inclusion
     *
     * @since 2.7
     */
    public JsonInclude.Value findPropertyInclusion(MapperConfig<?> config, Class<?> baseType);

    /**
     * Method for accessing set of possible alternate names that are accepted
     * during deserialization.
     *
     * @return List (possibly empty) of alternate names; never null
     *
     * @since 2.9
     */
    public List<PropertyName> findAliases(MapperConfig<?> config);

    /*
    /**********************************************************
    /* Schema/introspection support
    /**********************************************************
     */
    
    /**
     * Method that can be called to visit the type structure that this
     * property is part of.
     * Note that not all implementations support traversal with this
     * method; those that do not should throw
     * {@link UnsupportedOperationException}.
     *<p>
     * NOTE: Starting with 2.7, takes explicit {@link SerializerProvider}
     * argument to reduce the need to rely on provider visitor may or may not
     * have assigned.
     * 
     * @param objectVisitor Visitor to used as the callback handler
     * 
     * @since 2.2 (although signature did change in 2.7)
     */
    public void depositSchemaProperty(JsonObjectFormatVisitor objectVisitor,
            SerializerProvider provider)
        throws JsonMappingException;

    /*
    /**********************************************************
    /* Helper classes
    /**********************************************************
     */

    /**
     * Simple stand-alone implementation, useful as a placeholder
     * or base class for more complex implementations.
     */
    public static class Std implements BeanProperty,
        java.io.Serializable // 2.9
    {
        private static final long serialVersionUID = 1L;

        protected final PropertyName _name;
        protected final JavaType _type;
        protected final PropertyName _wrapperName;

        protected final PropertyMetadata _metadata;

        /**
         * Physical entity (field, method or constructor argument) that
         * is used to access value of property (or in case of constructor
         * property, just placeholder)
         */
        protected final AnnotatedMember _member;

        public Std(PropertyName name, JavaType type, PropertyName wrapperName,
                AnnotatedMember member, PropertyMetadata metadata)
        {
            _name = name;
            _type = type;
            _wrapperName = wrapperName;
            _metadata = metadata;
            _member = member;
        }

        /**
         * @deprecated Since 2.9
         */
        @Deprecated
        public Std(PropertyName name, JavaType type, PropertyName wrapperName,
                Annotations contextAnnotations,
                AnnotatedMember member, PropertyMetadata metadata)
        {
            this(name, type, wrapperName, member, metadata);
        }

        /**
         * @since 2.6
         */
        public Std(Std base, JavaType newType) {
            this(base._name, newType, base._wrapperName, base._member, base._metadata);
        }

        public Std withType(JavaType type) {
            return new Std(this, type);
        }

        @Override
        public <A extends Annotation> A getAnnotation(Class<A> acls) {
            return (_member == null) ? null : _member.getAnnotation(acls);
        }

        @Override
        public <A extends Annotation> A getContextAnnotation(Class<A> acls) {
            return null;
        }

        @Override
        @Deprecated
        public JsonFormat.Value findFormatOverrides(AnnotationIntrospector intr) {
            if ((_member != null) && (intr != null)) {
                JsonFormat.Value v = intr.findFormat(_member);
                if (v != null) {
                    return v;
                }
            }
            return EMPTY_FORMAT;
        }

        @Override
        public JsonFormat.Value findPropertyFormat(MapperConfig<?> config, Class<?> baseType) {
            JsonFormat.Value v0 = config.getDefaultPropertyFormat(baseType);
            AnnotationIntrospector intr = config.getAnnotationIntrospector();
            if ((intr == null) || (_member == null)) {
                return v0;
            }
            JsonFormat.Value v = intr.findFormat(_member);
            if (v == null) {
                return v0;
            }
            return v0.withOverrides(v);
        }
        
        @Override
        public JsonInclude.Value findPropertyInclusion(MapperConfig<?> config, Class<?> baseType)
        {
            JsonInclude.Value v0 = config.getDefaultInclusion(baseType, _type.getRawClass());
            AnnotationIntrospector intr = config.getAnnotationIntrospector();
            if ((intr == null) || (_member == null)) {
                return v0;
            }
            JsonInclude.Value v = intr.findPropertyInclusion(_member);
            if (v == null) {
                return v0;
            }
            return v0.withOverrides(v);
        }

        @Override
        public List<PropertyName> findAliases(MapperConfig<?> config) {
            // 26-Feb-2017, tatu: Do we really need to allow actual definition?
            //    For now, let's not.
            return Collections.emptyList();
        }

        @Override public String getName() { return _name.getSimpleName(); }
        @Override public PropertyName getFullName() { return _name; }
        @Override public JavaType getType() { return _type; }
        @Override public PropertyName getWrapperName() { return _wrapperName; }
        @Override public boolean isRequired() { return _metadata.isRequired(); }
        @Override public PropertyMetadata getMetadata() { return _metadata; }
        @Override public AnnotatedMember getMember() { return _member; }

        @Override
        public boolean isVirtual() { return false; }

        /**
         * Implementation of this method throws
         * {@link UnsupportedOperationException}, since instances of this
         * implementation should not be used as part of actual structure
         * visited. Rather, other implementations should handle it.
         */
        @Override
        public void depositSchemaProperty(JsonObjectFormatVisitor objectVisitor,
                SerializerProvider provider) {
            throw new UnsupportedOperationException("Instances of "+getClass().getName()+" should not get visited");
        }
    }

    /**
     * Alternative "Null" implementation that can be used in cases where a non-null
     * {@link BeanProperty} is needed
     *
     * @since 2.9
     */
    public static class Bogus implements BeanProperty
    {
        @Override
        public String getName() {
            return "";
        }

        @Override
        public PropertyName getFullName() {
            return PropertyName.NO_NAME;
        }

        @Override
        public JavaType getType() {
            return TypeFactory.unknownType();
        }

        @Override
        public PropertyName getWrapperName() {
            return null;
        }

        @Override
        public PropertyMetadata getMetadata() {
            return PropertyMetadata.STD_REQUIRED_OR_OPTIONAL;
        }

        @Override
        public boolean isRequired() {
            return false;
        }

        @Override
        public boolean isVirtual() {
            return false;
        }

        @Override
        public <A extends Annotation> A getAnnotation(Class<A> acls) {
            return null;
        }

        @Override
        public <A extends Annotation> A getContextAnnotation(Class<A> acls) {
            return null;
        }

        @Override
        public AnnotatedMember getMember() {
            return null;
        }

        @Override
        @Deprecated
        public Value findFormatOverrides(AnnotationIntrospector intr) {
            return Value.empty();
        }

        @Override
        public Value findPropertyFormat(MapperConfig<?> config, Class<?> baseType) {
            return Value.empty();
        }

        @Override
        public com.fasterxml.jackson.annotation.JsonInclude.Value findPropertyInclusion(
                MapperConfig<?> config, Class<?> baseType)
        {
            return null;
        }

        @Override
        public List<PropertyName> findAliases(MapperConfig<?> config) {
            return Collections.emptyList();
        }

        @Override
        public void depositSchemaProperty(JsonObjectFormatVisitor objectVisitor,
                SerializerProvider provider) throws JsonMappingException {
        }
    }
}