• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 package com.fasterxml.jackson.annotation;
2 
3 /**
4  * Definition of API used for constructing Object Identifiers
5  * (as annotated using {@link JsonIdentityInfo}).
6  * Also defines factory methods used for creating instances
7  * for serialization, deserialization.
8  *
9  * @param <T> Type of Object Identifiers produced.
10  */
11 @SuppressWarnings("serial")
12 public abstract class ObjectIdGenerator<T>
13     implements java.io.Serializable
14 {
15     /*
16     /**********************************************************
17     /* Accessors
18     /**********************************************************
19      */
20 
getScope()21     public abstract Class<?> getScope();
22 
23     /**
24      * Method called to check whether this generator instance can
25      * be used for Object Ids of specific generator type and
26      * scope; determination is based by passing a configured
27      * "blueprint" (prototype) instance; from which the actual
28      * instances are created (using {@link #newForSerialization}).
29      *
30      * @return True if this instance can be used as-is; false if not
31      */
canUseFor(ObjectIdGenerator<?> gen)32     public abstract boolean canUseFor(ObjectIdGenerator<?> gen);
33 
34     /**
35      * Accessor that needs to be overridden to return <code>true</code>
36      * if the Object Id may be serialized as JSON Object; used by, for example,
37      * JSOG handling.
38      * The reason accessor is needed is because handling such Object Ids is
39      * more complex and may incur additional buffering or performance overhead,
40      * avoiding of which makes sense for common case of scalar object ids
41      * (or native object ids some formats support).
42      *<p>
43      * Default implementation returns <code>false</code>, so needs to be overridden
44      * by Object-producing generators.
45      *
46      * @since 2.5
47      */
maySerializeAsObject()48     public boolean maySerializeAsObject() {
49         return false;
50     }
51 
52     /**
53      * Accessor that may be called (after verifying (via {@link #maySerializeAsObject()})
54      * whether given name
55      *
56      * @param name Name of property to check
57      * @param parser Parser that points to property name, in case generator needs
58      *    further verification (note: untyped, because <code>JsonParser</code> is defined
59      *    in `jackson-core`, and this package does not depend on it).
60      *
61      * @since 2.5
62      */
isValidReferencePropertyName(String name, Object parser)63     public boolean isValidReferencePropertyName(String name, Object parser) {
64         return false;
65     }
66 
67     /*
68     /**********************************************************
69     /* Factory methods
70     /**********************************************************
71      */
72 
73     /**
74      * Factory method to create a blueprint instance for specified
75      * scope. Generators that do not use scope may return 'this'.
76      */
forScope(Class<?> scope)77     public abstract ObjectIdGenerator<T> forScope(Class<?> scope);
78 
79     /**
80      * Factory method called to create a new instance to use for
81      * serialization: needed since generators may have state
82      * (next id to produce).
83      *<p>
84      * Note that actual type of 'context' is
85      * <code>com.fasterxml.jackson.databind.SerializerProvider</code>,
86      * but can not be declared here as type itself (as well as call
87      * to this object) comes from databind package.
88      *
89      * @param context Serialization context object used (of type
90      *    <code>com.fasterxml.jackson.databind.SerializerProvider</code>;
91      *    may be needed by more complex generators to access contextual
92      *    information such as configuration.
93      */
newForSerialization(Object context)94     public abstract ObjectIdGenerator<T> newForSerialization(Object context);
95 
96     /**
97      * Method for constructing key to use for ObjectId-to-POJO maps.
98      */
key(Object key)99     public abstract IdKey key(Object key);
100 
101     /*
102     /**********************************************************
103     /* Methods for serialization
104     /**********************************************************
105      */
106 
107     /**
108      * Method used for generating a new Object Identifier to serialize
109      * for given POJO.
110      *
111      * @param forPojo POJO for which identifier is needed
112      *
113      * @return Object Identifier to use.
114      */
generateId(Object forPojo)115     public abstract T generateId(Object forPojo);
116 
117     /*
118     /**********************************************************
119     /* Helper classes
120     /**********************************************************
121      */
122 
123     /**
124      * Simple key class that can be used as a key for
125      * ObjectId-to-POJO mappings, when multiple ObjectId types
126      * and scopes are used.
127      */
128     public final static class IdKey
129         implements java.io.Serializable
130     {
131         private static final long serialVersionUID = 1L;
132 
133         /**
134          * Type of {@link ObjectIdGenerator} used for generating Object Id
135          */
136         public final Class<?> type;
137 
138         /**
139          * Scope of the Object Id (may be null, to denote global)
140          */
141         public final Class<?> scope;
142 
143         /**
144          * Object for which Object Id was generated: can NOT be null.
145          */
146         public final Object key;
147 
148         private final int hashCode;
149 
IdKey(Class<?> type, Class<?> scope, Object key)150         public IdKey(Class<?> type, Class<?> scope, Object key) {
151             if (key == null) {
152                 throw new IllegalArgumentException("Can not construct IdKey for null key");
153             }
154             this.type = type;
155             this.scope = scope;
156             this.key = key;
157 
158             int h = key.hashCode() + type.getName().hashCode();
159             if (scope != null) {
160                 h ^= scope.getName().hashCode();
161             }
162             hashCode = h;
163         }
164 
165         @Override
hashCode()166         public int hashCode() { return hashCode; }
167 
168         @Override
equals(Object o)169         public boolean equals(Object o)
170         {
171             if (o == this) return true;
172             if (o == null) return false;
173             if (o.getClass() != getClass()) return false;
174             IdKey other = (IdKey) o;
175             return (other.key.equals(key)) && (other.type == type) && (other.scope == scope);
176         }
177 
178         @Override
toString()179         public String toString() {
180             return String.format("[ObjectId: key=%s, type=%s, scope=%s]", key,
181                     (type == null) ? "NONE" : type.getName(),
182                     (scope == null) ? "NONE" : scope.getName());
183         }
184     }
185 }
186