1
16 package org.springframework.data.mapping.model;
17
18 import java.util.Collection;
19 import java.util.Collections;
20 import java.util.Date;
21 import java.util.HashSet;
22 import java.util.Locale;
23 import java.util.Map;
24 import java.util.Map.Entry;
25 import java.util.Set;
26 import java.util.WeakHashMap;
27
28 import org.springframework.util.Assert;
29
30
37 public class SimpleTypeHolder {
38
39 private static final Set<Class<?>> DEFAULTS = new HashSet<Class<?>>() {
40
41 private static final long serialVersionUID = -1738594126505221500L;
42
43 {
44 add(boolean.class);
45 add(boolean[].class);
46 add(long.class);
47 add(long[].class);
48 add(short.class);
49 add(short[].class);
50 add(int.class);
51 add(int[].class);
52 add(byte.class);
53 add(byte[].class);
54 add(float.class);
55 add(float[].class);
56 add(double.class);
57 add(double[].class);
58 add(char.class);
59 add(char[].class);
60 add(Boolean.class);
61 add(Long.class);
62 add(Short.class);
63 add(Integer.class);
64 add(Byte.class);
65 add(Float.class);
66 add(Double.class);
67 add(Character.class);
68 add(String.class);
69 add(Date.class);
70 add(Locale.class);
71 add(Class.class);
72 add(Enum.class);
73 }
74 };
75 public static final SimpleTypeHolder DEFAULT = new SimpleTypeHolder();
76
77 private volatile Map<Class<?>, Boolean> simpleTypes;
78
79
84 protected SimpleTypeHolder() {
85 this(Collections.emptySet(), true);
86 }
87
88
95 public SimpleTypeHolder(Set<? extends Class<?>> customSimpleTypes, boolean registerDefaults) {
96
97 Assert.notNull(customSimpleTypes, "CustomSimpleTypes must not be null!");
98
99 this.simpleTypes = new WeakHashMap<>(customSimpleTypes.size() + DEFAULTS.size());
100
101 register(customSimpleTypes);
102
103 if (registerDefaults) {
104 register(DEFAULTS);
105 }
106 }
107
108
114 public SimpleTypeHolder(Set<? extends Class<?>> customSimpleTypes, SimpleTypeHolder source) {
115
116 Assert.notNull(customSimpleTypes, "CustomSimpleTypes must not be null!");
117 Assert.notNull(source, "SourceTypeHolder must not be null!");
118
119 this.simpleTypes = new WeakHashMap<>(customSimpleTypes.size() + source.simpleTypes.size());
120
121 register(customSimpleTypes);
122 registerCachePositives(source.simpleTypes);
123 }
124
125 private void registerCachePositives(Map<Class<?>, Boolean> source) {
126
127 for (Entry<Class<?>, Boolean> entry : source.entrySet()) {
128
129 if (!entry.getValue()) {
130 continue;
131 }
132
133 this.simpleTypes.put(entry.getKey(), true);
134 }
135 }
136
137
143 public boolean isSimpleType(Class<?> type) {
144
145 Assert.notNull(type, "Type must not be null!");
146
147 Map<Class<?>, Boolean> localSimpleTypes = this.simpleTypes;
148 Boolean isSimpleType = localSimpleTypes.get(type);
149
150 if (Object.class.equals(type) || Enum.class.isAssignableFrom(type)) {
151 return true;
152 }
153
154 if (isSimpleType != null) {
155 return isSimpleType;
156 }
157
158 String typeName = type.getName();
159
160 if (typeName.startsWith("java.lang") || type.getName().startsWith("java.time") || typeName.equals("kotlin.Unit")) {
161 return true;
162 }
163
164 for (Class<?> simpleType : localSimpleTypes.keySet()) {
165
166 if (simpleType.isAssignableFrom(type)) {
167
168 isSimpleType = localSimpleTypes.get(simpleType);
169 this.simpleTypes = put(localSimpleTypes, type, isSimpleType);
170 return isSimpleType;
171 }
172 }
173
174 this.simpleTypes = put(localSimpleTypes, type, false);
175
176 return false;
177 }
178
179 private void register(Collection<? extends Class<?>> types) {
180 types.forEach(customSimpleType -> this.simpleTypes.put(customSimpleType, true));
181 }
182
183 private static Map<Class<?>, Boolean> put(Map<Class<?>, Boolean> simpleTypes, Class<?> type, boolean isSimpleType) {
184
185 Map<Class<?>, Boolean> copy = new WeakHashMap<>(simpleTypes);
186 copy.put(type, isSimpleType);
187
188 return copy;
189 }
190 }
191