1 package com.fasterxml.jackson.databind.ser.impl;
2
3 import java.util.*;
4
5 import com.fasterxml.jackson.databind.JavaType;
6 import com.fasterxml.jackson.databind.JsonSerializer;
7 import com.fasterxml.jackson.databind.util.TypeKey;
8
9
18 public final class ReadOnlyClassToSerializerMap
19 {
20 private final Bucket[] _buckets;
21
22 private final int _size;
23
24 private final int _mask;
25
26 public ReadOnlyClassToSerializerMap(Map<TypeKey,JsonSerializer<Object>> serializers)
27 {
28 int size = findSize(serializers.size());
29 _size = size;
30 _mask = (size-1);
31 Bucket[] buckets = new Bucket[size];
32 for (Map.Entry<TypeKey,JsonSerializer<Object>> entry : serializers.entrySet()) {
33 TypeKey key = entry.getKey();
34 int index = key.hashCode() & _mask;
35 buckets[index] = new Bucket(buckets[index], key, entry.getValue());
36 }
37 _buckets = buckets;
38 }
39
40 private final static int findSize(int size)
41 {
42
43 int needed = (size <= 64) ? (size + size) : (size + (size >> 2));
44 int result = 8;
45 while (result < needed) {
46 result += result;
47 }
48 return result;
49 }
50
51
54 public static ReadOnlyClassToSerializerMap from(HashMap<TypeKey, JsonSerializer<Object>> src) {
55 return new ReadOnlyClassToSerializerMap(src);
56 }
57
58
63
64 public int size() { return _size; }
65
66 public JsonSerializer<Object> typedValueSerializer(JavaType type)
67 {
68 Bucket bucket = _buckets[TypeKey.typedHash(type) & _mask];
69 if (bucket == null) {
70 return null;
71 }
72 if (bucket.matchesTyped(type)) {
73 return bucket.value;
74 }
75 while ((bucket = bucket.next) != null) {
76 if (bucket.matchesTyped(type)) {
77 return bucket.value;
78 }
79 }
80 return null;
81 }
82
83 public JsonSerializer<Object> typedValueSerializer(Class<?> type)
84 {
85 Bucket bucket = _buckets[TypeKey.typedHash(type) & _mask];
86 if (bucket == null) {
87 return null;
88 }
89 if (bucket.matchesTyped(type)) {
90 return bucket.value;
91 }
92 while ((bucket = bucket.next) != null) {
93 if (bucket.matchesTyped(type)) {
94 return bucket.value;
95 }
96 }
97 return null;
98 }
99
100 public JsonSerializer<Object> untypedValueSerializer(JavaType type)
101 {
102 Bucket bucket = _buckets[TypeKey.untypedHash(type) & _mask];
103 if (bucket == null) {
104 return null;
105 }
106 if (bucket.matchesUntyped(type)) {
107 return bucket.value;
108 }
109 while ((bucket = bucket.next) != null) {
110 if (bucket.matchesUntyped(type)) {
111 return bucket.value;
112 }
113 }
114 return null;
115 }
116
117 public JsonSerializer<Object> untypedValueSerializer(Class<?> type)
118 {
119 Bucket bucket = _buckets[TypeKey.untypedHash(type) & _mask];
120 if (bucket == null) {
121 return null;
122 }
123 if (bucket.matchesUntyped(type)) {
124 return bucket.value;
125 }
126 while ((bucket = bucket.next) != null) {
127 if (bucket.matchesUntyped(type)) {
128 return bucket.value;
129 }
130 }
131 return null;
132 }
133
134
139
140 private final static class Bucket
141 {
142 public final JsonSerializer<Object> value;
143 public final Bucket next;
144
145 protected final Class<?> _class;
146 protected final JavaType _type;
147
148 protected final boolean _isTyped;
149
150 public Bucket(Bucket next, TypeKey key, JsonSerializer<Object> value)
151 {
152 this.next = next;
153 this.value = value;
154 _isTyped = key.isTyped();
155 _class = key.getRawType();
156 _type = key.getType();
157 }
158
159 public boolean matchesTyped(Class<?> key) {
160 return (_class == key) && _isTyped;
161 }
162
163 public boolean matchesUntyped(Class<?> key) {
164 return (_class == key) && !_isTyped;
165 }
166
167 public boolean matchesTyped(JavaType key) {
168 return _isTyped && key.equals(_type);
169 }
170
171 public boolean matchesUntyped(JavaType key) {
172 return !_isTyped && key.equals(_type);
173 }
174 }
175 }
176