1 package com.fasterxml.jackson.annotation; 2 3 import java.util.UUID; 4 5 /** 6 * Container class for standard {@link ObjectIdGenerator} implementations: 7 *<ul> 8 * <li>{@link IntSequenceGenerator} 9 * <li>{@link PropertyGenerator} 10 * <li>{@link StringIdGenerator} (since 2.7) 11 * <li>{@link UUIDGenerator} 12 *</ul> 13 *<p> 14 * NOTE: {@link PropertyGenerator} applicability is limited in one case: it can only 15 * be used on polymorphic base types (ones indicated using {@link JsonTypeInfo} or 16 * default typing) via class annotations: property annotation will fail due to lack 17 * of access to property, needed to determine type of Object Id for deserialization. 18 * This limitation may be lifted in future versions but it is the limitation at least 19 * up to and including Jackson 2.9. 20 */ 21 public class ObjectIdGenerators 22 { 23 /** 24 * Shared base class for concrete implementations. 25 */ 26 @SuppressWarnings("serial") 27 private abstract static class Base<T> extends ObjectIdGenerator<T> 28 { 29 protected final Class<?> _scope; 30 Base(Class<?> scope)31 protected Base(Class<?> scope) { 32 _scope = scope; 33 } 34 35 @Override getScope()36 public final Class<?> getScope() { 37 return _scope; 38 } 39 40 @Override canUseFor(ObjectIdGenerator<?> gen)41 public boolean canUseFor(ObjectIdGenerator<?> gen) { 42 return (gen.getClass() == getClass()) && (gen.getScope() == _scope); 43 } 44 45 @Override generateId(Object forPojo)46 public abstract T generateId(Object forPojo); 47 } 48 49 /* 50 /********************************************************** 51 /* Implementation classes 52 /********************************************************** 53 */ 54 55 /** 56 * Abstract marker class used to allow explicitly specifying 57 * that no generator is used; which also implies that no 58 * Object Id is to be included or used. 59 */ 60 @SuppressWarnings("serial") 61 public abstract static class None extends ObjectIdGenerator<Object> { } 62 63 /** 64 * Abstract place-holder class which is used to denote case 65 * where Object Identifier to use comes from a POJO property 66 * (getter method or field). If so, value is written directly 67 * during serialization, and used as-is during deserialization. 68 *<p> 69 * Actual implementation class is part of <code>databind</code> 70 * package. 71 */ 72 public abstract static class PropertyGenerator extends Base<Object> { 73 private static final long serialVersionUID = 1L; 74 PropertyGenerator(Class<?> scope)75 protected PropertyGenerator(Class<?> scope) { super(scope); } 76 } 77 78 /** 79 * Simple sequence-number based generator, which uses basic Java 80 * <code>int</code>s (starting with value 1) as Object Identifiers. 81 */ 82 public final static class IntSequenceGenerator extends Base<Integer> 83 { 84 private static final long serialVersionUID = 1L; 85 86 protected transient int _nextValue; 87 IntSequenceGenerator()88 public IntSequenceGenerator() { this(Object.class, -1); } IntSequenceGenerator(Class<?> scope, int fv)89 public IntSequenceGenerator(Class<?> scope, int fv) { 90 super(scope); 91 _nextValue = fv; 92 } 93 initialValue()94 protected int initialValue() { return 1; } 95 96 @Override forScope(Class<?> scope)97 public ObjectIdGenerator<Integer> forScope(Class<?> scope) { 98 return (_scope == scope) ? this : new IntSequenceGenerator(scope, _nextValue); 99 } 100 101 @Override newForSerialization(Object context)102 public ObjectIdGenerator<Integer> newForSerialization(Object context) { 103 return new IntSequenceGenerator(_scope, initialValue()); 104 } 105 106 @Override key(Object key)107 public IdKey key(Object key) { 108 // 02-Apr-2015, tatu: As per [annotations#56], should check for null 109 if (key == null) { 110 return null; 111 } 112 return new IdKey(getClass(), _scope, key); 113 } 114 115 @Override generateId(Object forPojo)116 public Integer generateId(Object forPojo) { 117 // 02-Apr-2015, tatu: As per [annotations#56], should check for null 118 if (forPojo == null) { 119 return null; 120 } 121 int id = _nextValue; 122 ++_nextValue; 123 return id; 124 } 125 } 126 127 /** 128 * Implementation that just uses {@link java.util.UUID}s as reliably 129 * unique identifiers: downside is that resulting String is 130 * 36 characters long. 131 *<p> 132 * One difference to other generators is that scope is always 133 * set as <code>Object.class</code> (regardless of arguments): this 134 * because UUIDs are globally unique, and scope has no meaning. 135 */ 136 public final static class UUIDGenerator extends Base<UUID> 137 { 138 private static final long serialVersionUID = 1L; 139 UUIDGenerator()140 public UUIDGenerator() { this(Object.class); } UUIDGenerator(Class<?> scope)141 private UUIDGenerator(Class<?> scope) { 142 super(Object.class); 143 } 144 145 /** 146 * Can just return base instance since this is essentially scopeless 147 */ 148 @Override forScope(Class<?> scope)149 public ObjectIdGenerator<UUID> forScope(Class<?> scope) { 150 return this; 151 } 152 153 /** 154 * Can just return base instance since this is essentially scopeless 155 */ 156 @Override newForSerialization(Object context)157 public ObjectIdGenerator<UUID> newForSerialization(Object context) { 158 return this; 159 } 160 161 @Override generateId(Object forPojo)162 public UUID generateId(Object forPojo) { 163 return UUID.randomUUID(); 164 } 165 166 @Override key(Object key)167 public IdKey key(Object key) { 168 // 02-Apr-2015, tatu: As per [annotations#56], should check for null 169 if (key == null) { 170 return null; 171 } 172 return new IdKey(getClass(), null, key); 173 } 174 175 /** 176 * Since UUIDs are always unique, let's fully ignore scope definition 177 */ 178 @Override canUseFor(ObjectIdGenerator<?> gen)179 public boolean canUseFor(ObjectIdGenerator<?> gen) { 180 return (gen.getClass() == getClass()); 181 } 182 } 183 184 /** 185 * Implementation that will accept arbitrary (but unique) String Ids on 186 * deserialization, and (by default) use random UUID generation similar 187 * to {@link UUIDGenerator} for generation ids. 188 *<p> 189 * This generator is most useful for cases where another system creates 190 * String Ids (of arbitrary structure, if any), and Jackson only needs to 191 * keep track of id-to-Object mapping. Generation also works, although if 192 * UUIDs are always used, {@link UUIDGenerator} is a better match as it 193 * will also validate ids being used. 194 * 195 * @since 2.7 196 */ 197 public final static class StringIdGenerator extends Base<String> 198 { 199 private static final long serialVersionUID = 1L; 200 StringIdGenerator()201 public StringIdGenerator() { this(Object.class); } StringIdGenerator(Class<?> scope)202 private StringIdGenerator(Class<?> scope) { 203 super(Object.class); 204 } 205 206 // Can just return base instance since this is essentially scopeless 207 @Override forScope(Class<?> scope)208 public ObjectIdGenerator<String> forScope(Class<?> scope) { 209 return this; 210 } 211 212 // Can just return base instance since this is essentially scopeless 213 @Override newForSerialization(Object context)214 public ObjectIdGenerator<String> newForSerialization(Object context) { 215 return this; 216 } 217 218 @Override generateId(Object forPojo)219 public String generateId(Object forPojo) { 220 return UUID.randomUUID().toString(); 221 } 222 223 @Override key(Object key)224 public IdKey key(Object key) { 225 if (key == null) { 226 return null; 227 } 228 return new IdKey(getClass(), null, key); 229 } 230 231 // Should be usable for generic Opaque String ids? 232 @Override canUseFor(ObjectIdGenerator<?> gen)233 public boolean canUseFor(ObjectIdGenerator<?> gen) { 234 return (gen instanceof StringIdGenerator); 235 } 236 } 237 } 238