• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

mybatis / mybatis-3 / 2604

03 Jan 2025 10:00AM UTC coverage: 87.524% (+0.3%) from 87.177%
2604

Pull #3146

github

web-flow
Merge 60c1f5fea into 8ac3920af
Pull Request #3146: Shared ambiguity instance

3633 of 4401 branches covered (82.55%)

4 of 4 new or added lines in 1 file covered. (100.0%)

254 existing lines in 22 files now uncovered.

9569 of 10933 relevant lines covered (87.52%)

0.88 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

93.01
/src/main/java/org/apache/ibatis/type/TypeHandlerRegistry.java
1
/*
2
 *    Copyright 2009-2024 the original author or authors.
3
 *
4
 *    Licensed under the Apache License, Version 2.0 (the "License");
5
 *    you may not use this file except in compliance with the License.
6
 *    You may obtain a copy of the License at
7
 *
8
 *       https://www.apache.org/licenses/LICENSE-2.0
9
 *
10
 *    Unless required by applicable law or agreed to in writing, software
11
 *    distributed under the License is distributed on an "AS IS" BASIS,
12
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
 *    See the License for the specific language governing permissions and
14
 *    limitations under the License.
15
 */
16
package org.apache.ibatis.type;
17

18
import java.io.InputStream;
19
import java.io.Reader;
20
import java.lang.reflect.Constructor;
21
import java.lang.reflect.Modifier;
22
import java.lang.reflect.Type;
23
import java.math.BigDecimal;
24
import java.math.BigInteger;
25
import java.sql.Time;
26
import java.sql.Timestamp;
27
import java.time.Instant;
28
import java.time.LocalDate;
29
import java.time.LocalDateTime;
30
import java.time.LocalTime;
31
import java.time.Month;
32
import java.time.OffsetDateTime;
33
import java.time.OffsetTime;
34
import java.time.Year;
35
import java.time.YearMonth;
36
import java.time.ZonedDateTime;
37
import java.time.chrono.JapaneseDate;
38
import java.util.Collection;
39
import java.util.Collections;
40
import java.util.Date;
41
import java.util.EnumMap;
42
import java.util.HashMap;
43
import java.util.Map;
44
import java.util.Map.Entry;
45
import java.util.Set;
46
import java.util.concurrent.ConcurrentHashMap;
47

48
import org.apache.ibatis.binding.MapperMethod.ParamMap;
49
import org.apache.ibatis.io.ResolverUtil;
50
import org.apache.ibatis.io.Resources;
51
import org.apache.ibatis.session.Configuration;
52

53
/**
54
 * @author Clinton Begin
55
 * @author Kazuki Shimizu
56
 */
57
public final class TypeHandlerRegistry {
58

59
  private final Map<JdbcType, TypeHandler<?>> jdbcTypeHandlerMap = new EnumMap<>(JdbcType.class);
1✔
60
  private final Map<Type, Map<JdbcType, TypeHandler<?>>> typeHandlerMap = new ConcurrentHashMap<>();
1✔
61
  private final TypeHandler<Object> unknownTypeHandler;
62
  private final Map<Class<?>, TypeHandler<?>> allTypeHandlersMap = new HashMap<>();
1✔
63

64
  private static final Map<JdbcType, TypeHandler<?>> NULL_TYPE_HANDLER_MAP = Collections.emptyMap();
1✔
65

66
  private Class<? extends TypeHandler> defaultEnumTypeHandler = EnumTypeHandler.class;
1✔
67

68
  /**
69
   * The default constructor.
70
   */
71
  public TypeHandlerRegistry() {
72
    this(new Configuration());
1✔
73
  }
1✔
74

75
  /**
76
   * The constructor that pass the MyBatis configuration.
77
   *
78
   * @param configuration
79
   *          a MyBatis configuration
80
   *
81
   * @since 3.5.4
82
   */
83
  public TypeHandlerRegistry(Configuration configuration) {
1✔
84
    this.unknownTypeHandler = new UnknownTypeHandler(configuration);
1✔
85

86
    register(Boolean.class, new BooleanTypeHandler());
1✔
87
    register(boolean.class, new BooleanTypeHandler());
1✔
88
    register(JdbcType.BOOLEAN, new BooleanTypeHandler());
1✔
89
    register(JdbcType.BIT, new BooleanTypeHandler());
1✔
90

91
    register(Byte.class, new ByteTypeHandler());
1✔
92
    register(byte.class, new ByteTypeHandler());
1✔
93
    register(JdbcType.TINYINT, new ByteTypeHandler());
1✔
94

95
    register(Short.class, new ShortTypeHandler());
1✔
96
    register(short.class, new ShortTypeHandler());
1✔
97
    register(JdbcType.SMALLINT, new ShortTypeHandler());
1✔
98

99
    register(Integer.class, new IntegerTypeHandler());
1✔
100
    register(int.class, new IntegerTypeHandler());
1✔
101
    register(JdbcType.INTEGER, new IntegerTypeHandler());
1✔
102

103
    register(Long.class, new LongTypeHandler());
1✔
104
    register(long.class, new LongTypeHandler());
1✔
105

106
    register(Float.class, new FloatTypeHandler());
1✔
107
    register(float.class, new FloatTypeHandler());
1✔
108
    register(JdbcType.FLOAT, new FloatTypeHandler());
1✔
109

110
    register(Double.class, new DoubleTypeHandler());
1✔
111
    register(double.class, new DoubleTypeHandler());
1✔
112
    register(JdbcType.DOUBLE, new DoubleTypeHandler());
1✔
113

114
    register(Reader.class, new ClobReaderTypeHandler());
1✔
115
    register(String.class, new StringTypeHandler());
1✔
116
    register(String.class, JdbcType.CHAR, new StringTypeHandler());
1✔
117
    register(String.class, JdbcType.CLOB, new ClobTypeHandler());
1✔
118
    register(String.class, JdbcType.VARCHAR, new StringTypeHandler());
1✔
119
    register(String.class, JdbcType.LONGVARCHAR, new StringTypeHandler());
1✔
120
    register(String.class, JdbcType.NVARCHAR, new NStringTypeHandler());
1✔
121
    register(String.class, JdbcType.NCHAR, new NStringTypeHandler());
1✔
122
    register(String.class, JdbcType.NCLOB, new NClobTypeHandler());
1✔
123
    register(JdbcType.CHAR, new StringTypeHandler());
1✔
124
    register(JdbcType.VARCHAR, new StringTypeHandler());
1✔
125
    register(JdbcType.CLOB, new ClobTypeHandler());
1✔
126
    register(JdbcType.LONGVARCHAR, new StringTypeHandler());
1✔
127
    register(JdbcType.NVARCHAR, new NStringTypeHandler());
1✔
128
    register(JdbcType.NCHAR, new NStringTypeHandler());
1✔
129
    register(JdbcType.NCLOB, new NClobTypeHandler());
1✔
130

131
    register(Object.class, JdbcType.ARRAY, new ArrayTypeHandler());
1✔
132
    register(JdbcType.ARRAY, new ArrayTypeHandler());
1✔
133

134
    register(BigInteger.class, new BigIntegerTypeHandler());
1✔
135
    register(JdbcType.BIGINT, new LongTypeHandler());
1✔
136

137
    register(BigDecimal.class, new BigDecimalTypeHandler());
1✔
138
    register(JdbcType.REAL, new BigDecimalTypeHandler());
1✔
139
    register(JdbcType.DECIMAL, new BigDecimalTypeHandler());
1✔
140
    register(JdbcType.NUMERIC, new BigDecimalTypeHandler());
1✔
141

142
    register(InputStream.class, new BlobInputStreamTypeHandler());
1✔
143
    register(Byte[].class, new ByteObjectArrayTypeHandler());
1✔
144
    register(Byte[].class, JdbcType.BLOB, new BlobByteObjectArrayTypeHandler());
1✔
145
    register(Byte[].class, JdbcType.LONGVARBINARY, new BlobByteObjectArrayTypeHandler());
1✔
146
    register(byte[].class, new ByteArrayTypeHandler());
1✔
147
    register(byte[].class, JdbcType.BLOB, new BlobTypeHandler());
1✔
148
    register(byte[].class, JdbcType.LONGVARBINARY, new BlobTypeHandler());
1✔
149
    register(JdbcType.LONGVARBINARY, new BlobTypeHandler());
1✔
150
    register(JdbcType.BLOB, new BlobTypeHandler());
1✔
151

152
    register(Object.class, unknownTypeHandler);
1✔
153
    register(Object.class, JdbcType.OTHER, unknownTypeHandler);
1✔
154
    register(JdbcType.OTHER, unknownTypeHandler);
1✔
155

156
    register(Date.class, new DateTypeHandler());
1✔
157
    register(Date.class, JdbcType.DATE, new DateOnlyTypeHandler());
1✔
158
    register(Date.class, JdbcType.TIME, new TimeOnlyTypeHandler());
1✔
159
    register(JdbcType.TIMESTAMP, new DateTypeHandler());
1✔
160
    register(JdbcType.DATE, new DateOnlyTypeHandler());
1✔
161
    register(JdbcType.TIME, new TimeOnlyTypeHandler());
1✔
162

163
    register(java.sql.Date.class, new SqlDateTypeHandler());
1✔
164
    register(Time.class, new SqlTimeTypeHandler());
1✔
165
    register(Timestamp.class, new SqlTimestampTypeHandler());
1✔
166

167
    register(String.class, JdbcType.SQLXML, new SqlxmlTypeHandler());
1✔
168

169
    register(Instant.class, new InstantTypeHandler());
1✔
170
    register(LocalDateTime.class, new LocalDateTimeTypeHandler());
1✔
171
    register(LocalDate.class, new LocalDateTypeHandler());
1✔
172
    register(LocalTime.class, new LocalTimeTypeHandler());
1✔
173
    register(OffsetDateTime.class, new OffsetDateTimeTypeHandler());
1✔
174
    register(OffsetTime.class, new OffsetTimeTypeHandler());
1✔
175
    register(ZonedDateTime.class, new ZonedDateTimeTypeHandler());
1✔
176
    register(Month.class, new MonthTypeHandler());
1✔
177
    register(Year.class, new YearTypeHandler());
1✔
178
    register(YearMonth.class, new YearMonthTypeHandler());
1✔
179
    register(JapaneseDate.class, new JapaneseDateTypeHandler());
1✔
180

181
    // issue #273
182
    register(Character.class, new CharacterTypeHandler());
1✔
183
    register(char.class, new CharacterTypeHandler());
1✔
184
  }
1✔
185

186
  /**
187
   * Set a default {@link TypeHandler} class for {@link Enum}. A default {@link TypeHandler} is
188
   * {@link org.apache.ibatis.type.EnumTypeHandler}.
189
   *
190
   * @param typeHandler
191
   *          a type handler class for {@link Enum}
192
   *
193
   * @since 3.4.5
194
   */
195
  public void setDefaultEnumTypeHandler(Class<? extends TypeHandler> typeHandler) {
UNCOV
196
    this.defaultEnumTypeHandler = typeHandler;
×
UNCOV
197
  }
×
198

199
  public boolean hasTypeHandler(Class<?> javaType) {
200
    return hasTypeHandler(javaType, null);
1✔
201
  }
202

203
  public boolean hasTypeHandler(TypeReference<?> javaTypeReference) {
UNCOV
204
    return hasTypeHandler(javaTypeReference, null);
×
205
  }
206

207
  public boolean hasTypeHandler(Class<?> javaType, JdbcType jdbcType) {
208
    return javaType != null && getTypeHandler((Type) javaType, jdbcType) != null;
1✔
209
  }
210

211
  public boolean hasTypeHandler(TypeReference<?> javaTypeReference, JdbcType jdbcType) {
UNCOV
212
    return javaTypeReference != null && getTypeHandler(javaTypeReference, jdbcType) != null;
×
213
  }
214

215
  public TypeHandler<?> getMappingTypeHandler(Class<? extends TypeHandler<?>> handlerType) {
216
    return allTypeHandlersMap.get(handlerType);
1✔
217
  }
218

219
  public <T> TypeHandler<T> getTypeHandler(Class<T> type) {
220
    return getTypeHandler((Type) type, null);
1✔
221
  }
222

223
  public <T> TypeHandler<T> getTypeHandler(TypeReference<T> javaTypeReference) {
224
    return getTypeHandler(javaTypeReference, null);
1✔
225
  }
226

227
  public TypeHandler<?> getTypeHandler(JdbcType jdbcType) {
UNCOV
228
    return jdbcTypeHandlerMap.get(jdbcType);
×
229
  }
230

231
  public <T> TypeHandler<T> getTypeHandler(Class<T> type, JdbcType jdbcType) {
232
    return getTypeHandler((Type) type, jdbcType);
1✔
233
  }
234

235
  public <T> TypeHandler<T> getTypeHandler(TypeReference<T> javaTypeReference, JdbcType jdbcType) {
236
    return getTypeHandler(javaTypeReference.getRawType(), jdbcType);
1✔
237
  }
238

239
  @SuppressWarnings("unchecked")
240
  private <T> TypeHandler<T> getTypeHandler(Type type, JdbcType jdbcType) {
241
    if (ParamMap.class.equals(type)) {
1✔
242
      return null;
1✔
243
    }
244
    Map<JdbcType, TypeHandler<?>> jdbcHandlerMap = getJdbcHandlerMap(type);
1✔
245
    TypeHandler<?> handler = null;
1✔
246
    if (jdbcHandlerMap != null) {
1✔
247
      handler = jdbcHandlerMap.get(jdbcType);
1✔
248
      if (handler == null) {
1✔
249
        handler = jdbcHandlerMap.get(null);
1✔
250
      }
251
      if (handler == null) {
1✔
252
        // #591
253
        handler = pickSoleHandler(jdbcHandlerMap);
1✔
254
      }
255
    }
256
    // type drives generics here
257
    return (TypeHandler<T>) handler;
1✔
258
  }
259

260
  private Map<JdbcType, TypeHandler<?>> getJdbcHandlerMap(Type type) {
261
    Map<JdbcType, TypeHandler<?>> jdbcHandlerMap = typeHandlerMap.get(type);
1✔
262
    if (jdbcHandlerMap != null) {
1✔
263
      return NULL_TYPE_HANDLER_MAP.equals(jdbcHandlerMap) ? null : jdbcHandlerMap;
1✔
264
    }
265
    if (type instanceof Class) {
1!
266
      Class<?> clazz = (Class<?>) type;
1✔
267
      if (Enum.class.isAssignableFrom(clazz)) {
1✔
268
        if (clazz.isAnonymousClass()) {
1✔
269
          return getJdbcHandlerMap(clazz.getSuperclass());
1✔
270
        }
271
        jdbcHandlerMap = getJdbcHandlerMapForEnumInterfaces(clazz, clazz);
1✔
272
        if (jdbcHandlerMap == null) {
1✔
273
          register(clazz, getInstance(clazz, defaultEnumTypeHandler));
1✔
274
          return typeHandlerMap.get(clazz);
1✔
275
        }
276
      } else {
277
        jdbcHandlerMap = getJdbcHandlerMapForSuperclass(clazz);
1✔
278
      }
279
    }
280
    typeHandlerMap.put(type, jdbcHandlerMap == null ? NULL_TYPE_HANDLER_MAP : jdbcHandlerMap);
1✔
281
    return jdbcHandlerMap;
1✔
282
  }
283

284
  private Map<JdbcType, TypeHandler<?>> getJdbcHandlerMapForEnumInterfaces(Class<?> clazz, Class<?> enumClazz) {
285
    for (Class<?> iface : clazz.getInterfaces()) {
1✔
286
      Map<JdbcType, TypeHandler<?>> jdbcHandlerMap = typeHandlerMap.get(iface);
1✔
287
      if (jdbcHandlerMap == null) {
1✔
288
        jdbcHandlerMap = getJdbcHandlerMapForEnumInterfaces(iface, enumClazz);
1✔
289
      }
290
      if (jdbcHandlerMap != null) {
1✔
291
        // Found a type handler registered to a super interface
292
        HashMap<JdbcType, TypeHandler<?>> newMap = new HashMap<>();
1✔
293
        for (Entry<JdbcType, TypeHandler<?>> entry : jdbcHandlerMap.entrySet()) {
1✔
294
          // Create a type handler instance with enum type as a constructor arg
295
          newMap.put(entry.getKey(), getInstance(enumClazz, entry.getValue().getClass()));
1✔
296
        }
1✔
297
        return newMap;
1✔
298
      }
299
    }
300
    return null;
1✔
301
  }
302

303
  private Map<JdbcType, TypeHandler<?>> getJdbcHandlerMapForSuperclass(Class<?> clazz) {
304
    Class<?> superclass = clazz.getSuperclass();
1✔
305
    if (superclass == null || Object.class.equals(superclass)) {
1✔
306
      return null;
1✔
307
    }
308
    Map<JdbcType, TypeHandler<?>> jdbcHandlerMap = typeHandlerMap.get(superclass);
1✔
309
    if (jdbcHandlerMap != null) {
1✔
310
      return jdbcHandlerMap;
1✔
311
    }
312
    return getJdbcHandlerMapForSuperclass(superclass);
1✔
313
  }
314

315
  private TypeHandler<?> pickSoleHandler(Map<JdbcType, TypeHandler<?>> jdbcHandlerMap) {
316
    TypeHandler<?> soleHandler = null;
1✔
317
    for (TypeHandler<?> handler : jdbcHandlerMap.values()) {
1✔
318
      if (soleHandler == null) {
1✔
319
        soleHandler = handler;
1✔
320
      } else if (!handler.getClass().equals(soleHandler.getClass())) {
1✔
321
        // More than one type handlers registered.
322
        return null;
1✔
323
      }
324
    }
1✔
325
    return soleHandler;
1✔
326
  }
327

328
  public TypeHandler<Object> getUnknownTypeHandler() {
329
    return unknownTypeHandler;
1✔
330
  }
331

332
  public void register(JdbcType jdbcType, TypeHandler<?> handler) {
333
    jdbcTypeHandlerMap.put(jdbcType, handler);
1✔
334
  }
1✔
335

336
  //
337
  // REGISTER INSTANCE
338
  //
339

340
  // Only handler
341

342
  @SuppressWarnings("unchecked")
343
  public <T> void register(TypeHandler<T> typeHandler) {
344
    boolean mappedTypeFound = false;
1✔
345
    MappedTypes mappedTypes = typeHandler.getClass().getAnnotation(MappedTypes.class);
1✔
346
    if (mappedTypes != null) {
1!
347
      for (Class<?> handledType : mappedTypes.value()) {
×
UNCOV
348
        register(handledType, typeHandler);
×
UNCOV
349
        mappedTypeFound = true;
×
350
      }
351
    }
352
    // @since 3.1.0 - try to auto-discover the mapped type
353
    if (!mappedTypeFound && typeHandler instanceof TypeReference) {
1!
354
      try {
355
        TypeReference<T> typeReference = (TypeReference<T>) typeHandler;
1✔
356
        register(typeReference.getRawType(), typeHandler);
1✔
357
        mappedTypeFound = true;
1✔
UNCOV
358
      } catch (Throwable t) {
×
359
        // maybe users define the TypeReference with a different type and are not assignable, so just ignore it
360
      }
1✔
361
    }
362
    if (!mappedTypeFound) {
1✔
363
      register((Class<T>) null, typeHandler);
1✔
364
    }
365
  }
1✔
366

367
  // java type + handler
368

369
  public <T> void register(Class<T> javaType, TypeHandler<? extends T> typeHandler) {
370
    register((Type) javaType, typeHandler);
1✔
371
  }
1✔
372

373
  private <T> void register(Type javaType, TypeHandler<? extends T> typeHandler) {
374
    MappedJdbcTypes mappedJdbcTypes = typeHandler.getClass().getAnnotation(MappedJdbcTypes.class);
1✔
375
    if (mappedJdbcTypes != null) {
1✔
376
      for (JdbcType handledJdbcType : mappedJdbcTypes.value()) {
1✔
377
        register(javaType, handledJdbcType, typeHandler);
1✔
378
      }
379
      if (mappedJdbcTypes.includeNullJdbcType()) {
1!
380
        register(javaType, null, typeHandler);
1✔
381
      }
382
    } else {
383
      register(javaType, null, typeHandler);
1✔
384
    }
385
  }
1✔
386

387
  public <T> void register(TypeReference<T> javaTypeReference, TypeHandler<? extends T> handler) {
388
    register(javaTypeReference.getRawType(), handler);
1✔
389
  }
1✔
390

391
  // java type + jdbc type + handler
392

393
  // Cast is required here
394
  @SuppressWarnings("cast")
395
  public <T> void register(Class<T> type, JdbcType jdbcType, TypeHandler<? extends T> handler) {
396
    register((Type) type, jdbcType, handler);
1✔
397
  }
1✔
398

399
  private void register(Type javaType, JdbcType jdbcType, TypeHandler<?> handler) {
400
    if (javaType != null) {
1✔
401
      Map<JdbcType, TypeHandler<?>> map = typeHandlerMap.get(javaType);
1✔
402
      if (map == null || map == NULL_TYPE_HANDLER_MAP) {
1✔
403
        map = new HashMap<>();
1✔
404
      }
405
      map.put(jdbcType, handler);
1✔
406
      typeHandlerMap.put(javaType, map);
1✔
407
    }
408
    allTypeHandlersMap.put(handler.getClass(), handler);
1✔
409
  }
1✔
410

411
  //
412
  // REGISTER CLASS
413
  //
414

415
  // Only handler type
416

417
  public void register(Class<?> typeHandlerClass) {
418
    boolean mappedTypeFound = false;
1✔
419
    MappedTypes mappedTypes = typeHandlerClass.getAnnotation(MappedTypes.class);
1✔
420
    if (mappedTypes != null) {
1✔
421
      for (Class<?> javaTypeClass : mappedTypes.value()) {
1✔
422
        register(javaTypeClass, typeHandlerClass);
1✔
423
        mappedTypeFound = true;
1✔
424
      }
425
    }
426
    if (!mappedTypeFound) {
1✔
427
      register(getInstance(null, typeHandlerClass));
1✔
428
    }
429
  }
1✔
430

431
  // java type + handler type
432

433
  public void register(String javaTypeClassName, String typeHandlerClassName) throws ClassNotFoundException {
UNCOV
434
    register(Resources.classForName(javaTypeClassName), Resources.classForName(typeHandlerClassName));
×
UNCOV
435
  }
×
436

437
  public void register(Class<?> javaTypeClass, Class<?> typeHandlerClass) {
438
    register(javaTypeClass, getInstance(javaTypeClass, typeHandlerClass));
1✔
439
  }
1✔
440

441
  // java type + jdbc type + handler type
442

443
  public void register(Class<?> javaTypeClass, JdbcType jdbcType, Class<?> typeHandlerClass) {
444
    register(javaTypeClass, jdbcType, getInstance(javaTypeClass, typeHandlerClass));
1✔
445
  }
1✔
446

447
  // Construct a handler (used also from Builders)
448

449
  @SuppressWarnings("unchecked")
450
  public <T> TypeHandler<T> getInstance(Class<?> javaTypeClass, Class<?> typeHandlerClass) {
451
    if (javaTypeClass != null) {
1✔
452
      try {
453
        Constructor<?> c = typeHandlerClass.getConstructor(Class.class);
1✔
454
        return (TypeHandler<T>) c.newInstance(javaTypeClass);
1✔
455
      } catch (NoSuchMethodException ignored) {
1✔
456
        // ignored
UNCOV
457
      } catch (Exception e) {
×
UNCOV
458
        throw new TypeException("Failed invoking constructor for handler " + typeHandlerClass, e);
×
459
      }
1✔
460
    }
461
    try {
462
      Constructor<?> c = typeHandlerClass.getConstructor();
1✔
463
      return (TypeHandler<T>) c.newInstance();
1✔
UNCOV
464
    } catch (Exception e) {
×
UNCOV
465
      throw new TypeException("Unable to find a usable constructor for " + typeHandlerClass, e);
×
466
    }
467
  }
468

469
  // scan
470

471
  public void register(String packageName) {
472
    ResolverUtil<Class<?>> resolverUtil = new ResolverUtil<>();
1✔
473
    resolverUtil.find(new ResolverUtil.IsA(TypeHandler.class), packageName);
1✔
474
    Set<Class<? extends Class<?>>> handlerSet = resolverUtil.getClasses();
1✔
475
    for (Class<?> type : handlerSet) {
1✔
476
      // Ignore inner classes and interfaces (including package-info.java) and abstract classes
477
      if (!type.isAnonymousClass() && !type.isInterface() && !Modifier.isAbstract(type.getModifiers())) {
1!
478
        register(type);
1✔
479
      }
480
    }
1✔
481
  }
1✔
482

483
  // get information
484

485
  /**
486
   * Gets the type handlers.
487
   *
488
   * @return the type handlers
489
   *
490
   * @since 3.2.2
491
   */
492
  public Collection<TypeHandler<?>> getTypeHandlers() {
UNCOV
493
    return Collections.unmodifiableCollection(allTypeHandlersMap.values());
×
494
  }
495

496
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc