1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.apache.ibatis.session;
17
18 import java.util.Arrays;
19 import java.util.Collection;
20 import java.util.HashMap;
21 import java.util.HashSet;
22 import java.util.LinkedList;
23 import java.util.List;
24 import java.util.Map;
25 import java.util.Properties;
26 import java.util.Set;
27
28 import org.apache.ibatis.binding.MapperRegistry;
29 import org.apache.ibatis.builder.CacheRefResolver;
30 import org.apache.ibatis.builder.ResultMapResolver;
31 import org.apache.ibatis.builder.annotation.MethodResolver;
32 import org.apache.ibatis.builder.xml.XMLStatementBuilder;
33 import org.apache.ibatis.cache.Cache;
34 import org.apache.ibatis.cache.decorators.FifoCache;
35 import org.apache.ibatis.cache.decorators.LruCache;
36 import org.apache.ibatis.cache.decorators.SoftCache;
37 import org.apache.ibatis.cache.decorators.WeakCache;
38 import org.apache.ibatis.cache.impl.PerpetualCache;
39 import org.apache.ibatis.datasource.jndi.JndiDataSourceFactory;
40 import org.apache.ibatis.datasource.pooled.PooledDataSourceFactory;
41 import org.apache.ibatis.datasource.unpooled.UnpooledDataSourceFactory;
42 import org.apache.ibatis.executor.BatchExecutor;
43 import org.apache.ibatis.executor.CachingExecutor;
44 import org.apache.ibatis.executor.Executor;
45 import org.apache.ibatis.executor.ReuseExecutor;
46 import org.apache.ibatis.executor.SimpleExecutor;
47 import org.apache.ibatis.executor.keygen.KeyGenerator;
48 import org.apache.ibatis.executor.loader.ProxyFactory;
49 import org.apache.ibatis.executor.loader.cglib.CglibProxyFactory;
50 import org.apache.ibatis.executor.loader.javassist.JavassistProxyFactory;
51 import org.apache.ibatis.executor.parameter.ParameterHandler;
52 import org.apache.ibatis.executor.resultset.DefaultResultSetHandler;
53 import org.apache.ibatis.executor.resultset.ResultSetHandler;
54 import org.apache.ibatis.executor.statement.RoutingStatementHandler;
55 import org.apache.ibatis.executor.statement.StatementHandler;
56 import org.apache.ibatis.logging.Log;
57 import org.apache.ibatis.logging.LogFactory;
58 import org.apache.ibatis.logging.commons.JakartaCommonsLoggingImpl;
59 import org.apache.ibatis.logging.jdk14.Jdk14LoggingImpl;
60 import org.apache.ibatis.logging.log4j.Log4jImpl;
61 import org.apache.ibatis.logging.log4j2.Log4j2Impl;
62 import org.apache.ibatis.logging.nologging.NoLoggingImpl;
63 import org.apache.ibatis.logging.slf4j.Slf4jImpl;
64 import org.apache.ibatis.logging.stdout.StdOutImpl;
65 import org.apache.ibatis.mapping.BoundSql;
66 import org.apache.ibatis.mapping.Environment;
67 import org.apache.ibatis.mapping.MappedStatement;
68 import org.apache.ibatis.mapping.ParameterMap;
69 import org.apache.ibatis.mapping.ResultMap;
70 import org.apache.ibatis.mapping.VendorDatabaseIdProvider;
71 import org.apache.ibatis.parsing.XNode;
72 import org.apache.ibatis.plugin.Interceptor;
73 import org.apache.ibatis.plugin.InterceptorChain;
74 import org.apache.ibatis.reflection.DefaultReflectorFactory;
75 import org.apache.ibatis.reflection.MetaObject;
76 import org.apache.ibatis.reflection.ReflectorFactory;
77 import org.apache.ibatis.reflection.factory.DefaultObjectFactory;
78 import org.apache.ibatis.reflection.factory.ObjectFactory;
79 import org.apache.ibatis.reflection.wrapper.DefaultObjectWrapperFactory;
80 import org.apache.ibatis.reflection.wrapper.ObjectWrapperFactory;
81 import org.apache.ibatis.scripting.LanguageDriver;
82 import org.apache.ibatis.scripting.LanguageDriverRegistry;
83 import org.apache.ibatis.scripting.defaults.RawLanguageDriver;
84 import org.apache.ibatis.scripting.xmltags.XMLLanguageDriver;
85 import org.apache.ibatis.transaction.Transaction;
86 import org.apache.ibatis.transaction.jdbc.JdbcTransactionFactory;
87 import org.apache.ibatis.transaction.managed.ManagedTransactionFactory;
88 import org.apache.ibatis.type.JdbcType;
89 import org.apache.ibatis.type.TypeAliasRegistry;
90 import org.apache.ibatis.type.TypeHandlerRegistry;
91
92
93
94
95 public class Configuration {
96
97 protected Environment environment;
98
99 protected boolean safeRowBoundsEnabled = false;
100 protected boolean safeResultHandlerEnabled = true;
101 protected boolean mapUnderscoreToCamelCase = false;
102 protected boolean aggressiveLazyLoading = true;
103 protected boolean multipleResultSetsEnabled = true;
104 protected boolean useGeneratedKeys = false;
105 protected boolean useColumnLabel = true;
106 protected boolean cacheEnabled = true;
107 protected boolean callSettersOnNulls = false;
108
109 protected String logPrefix;
110 protected Class <? extends Log> logImpl;
111 protected LocalCacheScope localCacheScope = LocalCacheScope.SESSION;
112 protected JdbcType jdbcTypeForNull = JdbcType.OTHER;
113 protected Set<String> lazyLoadTriggerMethods = new HashSet<String>(Arrays.asList(new String[] { "equals", "clone", "hashCode", "toString" }));
114 protected Integer defaultStatementTimeout;
115 protected Integer defaultFetchSize;
116 protected ExecutorType defaultExecutorType = ExecutorType.SIMPLE;
117 protected AutoMappingBehavior autoMappingBehavior = AutoMappingBehavior.PARTIAL;
118
119 protected Properties variables = new Properties();
120 protected ReflectorFactory reflectorFactory = new DefaultReflectorFactory();
121 protected ObjectFactory objectFactory = new DefaultObjectFactory();
122 protected ObjectWrapperFactory objectWrapperFactory = new DefaultObjectWrapperFactory();
123 protected MapperRegistry mapperRegistry = new MapperRegistry(this);
124
125 protected boolean lazyLoadingEnabled = false;
126 protected ProxyFactory proxyFactory = new JavassistProxyFactory();
127
128 protected String databaseId;
129
130
131
132
133
134
135 protected Class<?> configurationFactory;
136
137 protected final InterceptorChain interceptorChain = new InterceptorChain();
138 protected final TypeHandlerRegistry typeHandlerRegistry = new TypeHandlerRegistry();
139 protected final TypeAliasRegistry typeAliasRegistry = new TypeAliasRegistry();
140 protected final LanguageDriverRegistry languageRegistry = new LanguageDriverRegistry();
141
142 protected final Map<String, MappedStatement> mappedStatements = new StrictMap<MappedStatement>("Mapped Statements collection");
143 protected final Map<String, Cache> caches = new StrictMap<Cache>("Caches collection");
144 protected final Map<String, ResultMap> resultMaps = new StrictMap<ResultMap>("Result Maps collection");
145 protected final Map<String, ParameterMap> parameterMaps = new StrictMap<ParameterMap>("Parameter Maps collection");
146 protected final Map<String, KeyGenerator> keyGenerators = new StrictMap<KeyGenerator>("Key Generators collection");
147
148 protected final Set<String> loadedResources = new HashSet<String>();
149 protected final Map<String, XNode> sqlFragments = new StrictMap<XNode>("XML fragments parsed from previous mappers");
150
151 protected final Collection<XMLStatementBuilder> incompleteStatements = new LinkedList<XMLStatementBuilder>();
152 protected final Collection<CacheRefResolver> incompleteCacheRefs = new LinkedList<CacheRefResolver>();
153 protected final Collection<ResultMapResolver> incompleteResultMaps = new LinkedList<ResultMapResolver>();
154 protected final Collection<MethodResolver> incompleteMethods = new LinkedList<MethodResolver>();
155
156
157
158
159
160
161 protected final Map<String, String> cacheRefMap = new HashMap<String, String>();
162
163 public Configuration(Environment environment) {
164 this();
165 this.environment = environment;
166 }
167
168 public Configuration() {
169 typeAliasRegistry.registerAlias("JDBC", JdbcTransactionFactory.class);
170 typeAliasRegistry.registerAlias("MANAGED", ManagedTransactionFactory.class);
171
172 typeAliasRegistry.registerAlias("JNDI", JndiDataSourceFactory.class);
173 typeAliasRegistry.registerAlias("POOLED", PooledDataSourceFactory.class);
174 typeAliasRegistry.registerAlias("UNPOOLED", UnpooledDataSourceFactory.class);
175
176 typeAliasRegistry.registerAlias("PERPETUAL", PerpetualCache.class);
177 typeAliasRegistry.registerAlias("FIFO", FifoCache.class);
178 typeAliasRegistry.registerAlias("LRU", LruCache.class);
179 typeAliasRegistry.registerAlias("SOFT", SoftCache.class);
180 typeAliasRegistry.registerAlias("WEAK", WeakCache.class);
181
182 typeAliasRegistry.registerAlias("DB_VENDOR", VendorDatabaseIdProvider.class);
183
184 typeAliasRegistry.registerAlias("XML", XMLLanguageDriver.class);
185 typeAliasRegistry.registerAlias("RAW", RawLanguageDriver.class);
186
187 typeAliasRegistry.registerAlias("SLF4J", Slf4jImpl.class);
188 typeAliasRegistry.registerAlias("COMMONS_LOGGING", JakartaCommonsLoggingImpl.class);
189 typeAliasRegistry.registerAlias("LOG4J", Log4jImpl.class);
190 typeAliasRegistry.registerAlias("LOG4J2", Log4j2Impl.class);
191 typeAliasRegistry.registerAlias("JDK_LOGGING", Jdk14LoggingImpl.class);
192 typeAliasRegistry.registerAlias("STDOUT_LOGGING", StdOutImpl.class);
193 typeAliasRegistry.registerAlias("NO_LOGGING", NoLoggingImpl.class);
194
195 typeAliasRegistry.registerAlias("CGLIB", CglibProxyFactory.class);
196 typeAliasRegistry.registerAlias("JAVASSIST", JavassistProxyFactory.class);
197
198 languageRegistry.setDefaultDriverClass(XMLLanguageDriver.class);
199 languageRegistry.register(RawLanguageDriver.class);
200 }
201
202 public String getLogPrefix() {
203 return logPrefix;
204 }
205
206 public void setLogPrefix(String logPrefix) {
207 this.logPrefix = logPrefix;
208 }
209
210 public Class<? extends Log> getLogImpl() {
211 return logImpl;
212 }
213
214 @SuppressWarnings("unchecked")
215 public void setLogImpl(Class<?> logImpl) {
216 if (logImpl != null) {
217 this.logImpl = (Class<? extends Log>) logImpl;
218 LogFactory.useCustomLogging(this.logImpl);
219 }
220 }
221
222 public boolean isCallSettersOnNulls() {
223 return callSettersOnNulls;
224 }
225
226 public void setCallSettersOnNulls(boolean callSettersOnNulls) {
227 this.callSettersOnNulls = callSettersOnNulls;
228 }
229
230 public String getDatabaseId() {
231 return databaseId;
232 }
233
234 public void setDatabaseId(String databaseId) {
235 this.databaseId = databaseId;
236 }
237
238 public Class<?> getConfigurationFactory() {
239 return configurationFactory;
240 }
241
242 public void setConfigurationFactory(Class<?> configurationFactory) {
243 this.configurationFactory = configurationFactory;
244 }
245
246 public boolean isSafeResultHandlerEnabled() {
247 return safeResultHandlerEnabled;
248 }
249
250 public void setSafeResultHandlerEnabled(boolean safeResultHandlerEnabled) {
251 this.safeResultHandlerEnabled = safeResultHandlerEnabled;
252 }
253
254 public boolean isSafeRowBoundsEnabled() {
255 return safeRowBoundsEnabled;
256 }
257
258 public void setSafeRowBoundsEnabled(boolean safeRowBoundsEnabled) {
259 this.safeRowBoundsEnabled = safeRowBoundsEnabled;
260 }
261
262 public boolean isMapUnderscoreToCamelCase() {
263 return mapUnderscoreToCamelCase;
264 }
265
266 public void setMapUnderscoreToCamelCase(boolean mapUnderscoreToCamelCase) {
267 this.mapUnderscoreToCamelCase = mapUnderscoreToCamelCase;
268 }
269
270 public void addLoadedResource(String resource) {
271 loadedResources.add(resource);
272 }
273
274 public boolean isResourceLoaded(String resource) {
275 return loadedResources.contains(resource);
276 }
277
278 public Environment getEnvironment() {
279 return environment;
280 }
281
282 public void setEnvironment(Environment environment) {
283 this.environment = environment;
284 }
285
286 public AutoMappingBehavior getAutoMappingBehavior() {
287 return autoMappingBehavior;
288 }
289
290 public void setAutoMappingBehavior(AutoMappingBehavior autoMappingBehavior) {
291 this.autoMappingBehavior = autoMappingBehavior;
292 }
293
294 public boolean isLazyLoadingEnabled() {
295 return lazyLoadingEnabled;
296 }
297
298 public void setLazyLoadingEnabled(boolean lazyLoadingEnabled) {
299 this.lazyLoadingEnabled = lazyLoadingEnabled;
300 }
301
302 public ProxyFactory getProxyFactory() {
303 return proxyFactory;
304 }
305
306 public void setProxyFactory(ProxyFactory proxyFactory) {
307 if (proxyFactory == null) {
308 proxyFactory = new JavassistProxyFactory();
309 }
310 this.proxyFactory = proxyFactory;
311 }
312
313 public boolean isAggressiveLazyLoading() {
314 return aggressiveLazyLoading;
315 }
316
317 public void setAggressiveLazyLoading(boolean aggressiveLazyLoading) {
318 this.aggressiveLazyLoading = aggressiveLazyLoading;
319 }
320
321 public boolean isMultipleResultSetsEnabled() {
322 return multipleResultSetsEnabled;
323 }
324
325 public void setMultipleResultSetsEnabled(boolean multipleResultSetsEnabled) {
326 this.multipleResultSetsEnabled = multipleResultSetsEnabled;
327 }
328
329 public Set<String> getLazyLoadTriggerMethods() {
330 return lazyLoadTriggerMethods;
331 }
332
333 public void setLazyLoadTriggerMethods(Set<String> lazyLoadTriggerMethods) {
334 this.lazyLoadTriggerMethods = lazyLoadTriggerMethods;
335 }
336
337 public boolean isUseGeneratedKeys() {
338 return useGeneratedKeys;
339 }
340
341 public void setUseGeneratedKeys(boolean useGeneratedKeys) {
342 this.useGeneratedKeys = useGeneratedKeys;
343 }
344
345 public ExecutorType getDefaultExecutorType() {
346 return defaultExecutorType;
347 }
348
349 public void setDefaultExecutorType(ExecutorType defaultExecutorType) {
350 this.defaultExecutorType = defaultExecutorType;
351 }
352
353 public boolean isCacheEnabled() {
354 return cacheEnabled;
355 }
356
357 public void setCacheEnabled(boolean cacheEnabled) {
358 this.cacheEnabled = cacheEnabled;
359 }
360
361 public Integer getDefaultStatementTimeout() {
362 return defaultStatementTimeout;
363 }
364
365 public void setDefaultStatementTimeout(Integer defaultStatementTimeout) {
366 this.defaultStatementTimeout = defaultStatementTimeout;
367 }
368
369 public Integer getDefaultFetchSize() {
370 return defaultFetchSize;
371 }
372
373 public void setDefaultFetchSize(Integer defaultFetchSize) {
374 this.defaultFetchSize = defaultFetchSize;
375 }
376
377 public boolean isUseColumnLabel() {
378 return useColumnLabel;
379 }
380
381 public void setUseColumnLabel(boolean useColumnLabel) {
382 this.useColumnLabel = useColumnLabel;
383 }
384
385 public LocalCacheScope getLocalCacheScope() {
386 return localCacheScope;
387 }
388
389 public void setLocalCacheScope(LocalCacheScope localCacheScope) {
390 this.localCacheScope = localCacheScope;
391 }
392
393 public JdbcType getJdbcTypeForNull() {
394 return jdbcTypeForNull;
395 }
396
397 public void setJdbcTypeForNull(JdbcType jdbcTypeForNull) {
398 this.jdbcTypeForNull = jdbcTypeForNull;
399 }
400
401 public Properties getVariables() {
402 return variables;
403 }
404
405 public void setVariables(Properties variables) {
406 this.variables = variables;
407 }
408
409 public TypeHandlerRegistry getTypeHandlerRegistry() {
410 return typeHandlerRegistry;
411 }
412
413 public TypeAliasRegistry getTypeAliasRegistry() {
414 return typeAliasRegistry;
415 }
416
417
418
419
420 public MapperRegistry getMapperRegistry() {
421 return mapperRegistry;
422 }
423
424 public ReflectorFactory getReflectorFactory() {
425 return reflectorFactory;
426 }
427
428 public void setReflectorFactory(ReflectorFactory reflectorFactory) {
429 this.reflectorFactory = reflectorFactory;
430 }
431
432 public ObjectFactory getObjectFactory() {
433 return objectFactory;
434 }
435
436 public void setObjectFactory(ObjectFactory objectFactory) {
437 this.objectFactory = objectFactory;
438 }
439
440 public ObjectWrapperFactory getObjectWrapperFactory() {
441 return objectWrapperFactory;
442 }
443
444 public void setObjectWrapperFactory(ObjectWrapperFactory objectWrapperFactory) {
445 this.objectWrapperFactory = objectWrapperFactory;
446 }
447
448
449
450
451 public List<Interceptor> getInterceptors() {
452 return interceptorChain.getInterceptors();
453 }
454
455 public LanguageDriverRegistry getLanguageRegistry() {
456 return languageRegistry;
457 }
458
459 public void setDefaultScriptingLanguage(Class<?> driver) {
460 if (driver == null) {
461 driver = XMLLanguageDriver.class;
462 }
463 getLanguageRegistry().setDefaultDriverClass(driver);
464 }
465
466 public LanguageDriver getDefaultScriptingLanuageInstance() {
467 return languageRegistry.getDefaultDriver();
468 }
469
470 public MetaObject newMetaObject(Object object) {
471 return MetaObject.forObject(object, objectFactory, objectWrapperFactory, reflectorFactory);
472 }
473
474 public ParameterHandler newParameterHandler(MappedStatement mappedStatement, Object parameterObject, BoundSql boundSql) {
475 ParameterHandler parameterHandler = mappedStatement.getLang().createParameterHandler(mappedStatement, parameterObject, boundSql);
476 parameterHandler = (ParameterHandler) interceptorChain.pluginAll(parameterHandler);
477 return parameterHandler;
478 }
479
480 public ResultSetHandler newResultSetHandler(Executor executor, MappedStatement mappedStatement, RowBounds rowBounds, ParameterHandler parameterHandler,
481 ResultHandler resultHandler, BoundSql boundSql) {
482 ResultSetHandler resultSetHandler = new DefaultResultSetHandler(executor, mappedStatement, parameterHandler, resultHandler, boundSql, rowBounds);
483 resultSetHandler = (ResultSetHandler) interceptorChain.pluginAll(resultSetHandler);
484 return resultSetHandler;
485 }
486
487 public StatementHandler newStatementHandler(Executor executor, MappedStatement mappedStatement, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {
488 StatementHandler statementHandler = new RoutingStatementHandler(executor, mappedStatement, parameterObject, rowBounds, resultHandler, boundSql);
489 statementHandler = (StatementHandler) interceptorChain.pluginAll(statementHandler);
490 return statementHandler;
491 }
492
493 public Executor newExecutor(Transaction transaction) {
494 return newExecutor(transaction, defaultExecutorType);
495 }
496
497 public Executor newExecutor(Transaction transaction, ExecutorType executorType) {
498 executorType = executorType == null ? defaultExecutorType : executorType;
499 executorType = executorType == null ? ExecutorType.SIMPLE : executorType;
500 Executor executor;
501 if (ExecutorType.BATCH == executorType) {
502 executor = new BatchExecutor(this, transaction);
503 } else if (ExecutorType.REUSE == executorType) {
504 executor = new ReuseExecutor(this, transaction);
505 } else {
506 executor = new SimpleExecutor(this, transaction);
507 }
508 if (cacheEnabled) {
509 executor = new CachingExecutor(executor);
510 }
511 executor = (Executor) interceptorChain.pluginAll(executor);
512 return executor;
513 }
514
515 public void addKeyGenerator(String id, KeyGenerator keyGenerator) {
516 keyGenerators.put(id, keyGenerator);
517 }
518
519 public Collection<String> getKeyGeneratorNames() {
520 return keyGenerators.keySet();
521 }
522
523 public Collection<KeyGenerator> getKeyGenerators() {
524 return keyGenerators.values();
525 }
526
527 public KeyGenerator getKeyGenerator(String id) {
528 return keyGenerators.get(id);
529 }
530
531 public boolean hasKeyGenerator(String id) {
532 return keyGenerators.containsKey(id);
533 }
534
535 public void addCache(Cache cache) {
536 caches.put(cache.getId(), cache);
537 }
538
539 public Collection<String> getCacheNames() {
540 return caches.keySet();
541 }
542
543 public Collection<Cache> getCaches() {
544 return caches.values();
545 }
546
547 public Cache getCache(String id) {
548 return caches.get(id);
549 }
550
551 public boolean hasCache(String id) {
552 return caches.containsKey(id);
553 }
554
555 public void addResultMap(ResultMap rm) {
556 resultMaps.put(rm.getId(), rm);
557 checkLocallyForDiscriminatedNestedResultMaps(rm);
558 checkGloballyForDiscriminatedNestedResultMaps(rm);
559 }
560
561 public Collection<String> getResultMapNames() {
562 return resultMaps.keySet();
563 }
564
565 public Collection<ResultMap> getResultMaps() {
566 return resultMaps.values();
567 }
568
569 public ResultMap getResultMap(String id) {
570 return resultMaps.get(id);
571 }
572
573 public boolean hasResultMap(String id) {
574 return resultMaps.containsKey(id);
575 }
576
577 public void addParameterMap(ParameterMap pm) {
578 parameterMaps.put(pm.getId(), pm);
579 }
580
581 public Collection<String> getParameterMapNames() {
582 return parameterMaps.keySet();
583 }
584
585 public Collection<ParameterMap> getParameterMaps() {
586 return parameterMaps.values();
587 }
588
589 public ParameterMap getParameterMap(String id) {
590 return parameterMaps.get(id);
591 }
592
593 public boolean hasParameterMap(String id) {
594 return parameterMaps.containsKey(id);
595 }
596
597 public void addMappedStatement(MappedStatement ms) {
598 mappedStatements.put(ms.getId(), ms);
599 }
600
601 public Collection<String> getMappedStatementNames() {
602 buildAllStatements();
603 return mappedStatements.keySet();
604 }
605
606 public Collection<MappedStatement> getMappedStatements() {
607 buildAllStatements();
608 return mappedStatements.values();
609 }
610
611 public Collection<XMLStatementBuilder> getIncompleteStatements() {
612 return incompleteStatements;
613 }
614
615 public void addIncompleteStatement(XMLStatementBuilder incompleteStatement) {
616 incompleteStatements.add(incompleteStatement);
617 }
618
619 public Collection<CacheRefResolver> getIncompleteCacheRefs() {
620 return incompleteCacheRefs;
621 }
622
623 public void addIncompleteCacheRef(CacheRefResolver incompleteCacheRef) {
624 incompleteCacheRefs.add(incompleteCacheRef);
625 }
626
627 public Collection<ResultMapResolver> getIncompleteResultMaps() {
628 return incompleteResultMaps;
629 }
630
631 public void addIncompleteResultMap(ResultMapResolver resultMapResolver) {
632 incompleteResultMaps.add(resultMapResolver);
633 }
634
635 public void addIncompleteMethod(MethodResolver builder) {
636 incompleteMethods.add(builder);
637 }
638
639 public Collection<MethodResolver> getIncompleteMethods() {
640 return incompleteMethods;
641 }
642
643 public MappedStatement getMappedStatement(String id) {
644 return this.getMappedStatement(id, true);
645 }
646
647 public MappedStatement getMappedStatement(String id, boolean validateIncompleteStatements) {
648 if (validateIncompleteStatements) {
649 buildAllStatements();
650 }
651 return mappedStatements.get(id);
652 }
653
654 public Map<String, XNode> getSqlFragments() {
655 return sqlFragments;
656 }
657
658 public void addInterceptor(Interceptor interceptor) {
659 interceptorChain.addInterceptor(interceptor);
660 }
661
662 public void addMappers(String packageName, Class<?> superType) {
663 mapperRegistry.addMappers(packageName, superType);
664 }
665
666 public void addMappers(String packageName) {
667 mapperRegistry.addMappers(packageName);
668 }
669
670 public <T> void addMapper(Class<T> type) {
671 mapperRegistry.addMapper(type);
672 }
673
674 public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
675 return mapperRegistry.getMapper(type, sqlSession);
676 }
677
678 public boolean hasMapper(Class<?> type) {
679 return mapperRegistry.hasMapper(type);
680 }
681
682 public boolean hasStatement(String statementName) {
683 return hasStatement(statementName, true);
684 }
685
686 public boolean hasStatement(String statementName, boolean validateIncompleteStatements) {
687 if (validateIncompleteStatements) {
688 buildAllStatements();
689 }
690 return mappedStatements.containsKey(statementName);
691 }
692
693 public void addCacheRef(String namespace, String referencedNamespace) {
694 cacheRefMap.put(namespace, referencedNamespace);
695 }
696
697
698
699
700
701
702 protected void buildAllStatements() {
703 if (!incompleteResultMaps.isEmpty()) {
704 synchronized (incompleteResultMaps) {
705
706 incompleteResultMaps.iterator().next().resolve();
707 }
708 }
709 if (!incompleteCacheRefs.isEmpty()) {
710 synchronized (incompleteCacheRefs) {
711
712 incompleteCacheRefs.iterator().next().resolveCacheRef();
713 }
714 }
715 if (!incompleteStatements.isEmpty()) {
716 synchronized (incompleteStatements) {
717
718 incompleteStatements.iterator().next().parseStatementNode();
719 }
720 }
721 if (!incompleteMethods.isEmpty()) {
722 synchronized (incompleteMethods) {
723
724 incompleteMethods.iterator().next().resolve();
725 }
726 }
727 }
728
729
730
731
732
733
734
735 protected String extractNamespace(String statementId) {
736 int lastPeriod = statementId.lastIndexOf('.');
737 return lastPeriod > 0 ? statementId.substring(0, lastPeriod) : null;
738 }
739
740
741 protected void checkGloballyForDiscriminatedNestedResultMaps(ResultMap rm) {
742 if (rm.hasNestedResultMaps()) {
743 for (Map.Entry<String, ResultMap> entry : resultMaps.entrySet()) {
744 Object value = entry.getValue();
745 if (value instanceof ResultMap) {
746 ResultMap entryResultMap = (ResultMap) value;
747 if (!entryResultMap.hasNestedResultMaps() && entryResultMap.getDiscriminator() != null) {
748 Collection<String> discriminatedResultMapNames = entryResultMap.getDiscriminator().getDiscriminatorMap().values();
749 if (discriminatedResultMapNames.contains(rm.getId())) {
750 entryResultMap.forceNestedResultMaps();
751 }
752 }
753 }
754 }
755 }
756 }
757
758
759 protected void checkLocallyForDiscriminatedNestedResultMaps(ResultMap rm) {
760 if (!rm.hasNestedResultMaps() && rm.getDiscriminator() != null) {
761 for (Map.Entry<String, String> entry : rm.getDiscriminator().getDiscriminatorMap().entrySet()) {
762 String discriminatedResultMapName = entry.getValue();
763 if (hasResultMap(discriminatedResultMapName)) {
764 ResultMap discriminatedResultMap = resultMaps.get(discriminatedResultMapName);
765 if (discriminatedResultMap.hasNestedResultMaps()) {
766 rm.forceNestedResultMaps();
767 break;
768 }
769 }
770 }
771 }
772 }
773
774 protected static class StrictMap<V> extends HashMap<String, V> {
775
776 private static final long serialVersionUID = -4950446264854982944L;
777 private String name;
778
779 public StrictMap(String name, int initialCapacity, float loadFactor) {
780 super(initialCapacity, loadFactor);
781 this.name = name;
782 }
783
784 public StrictMap(String name, int initialCapacity) {
785 super(initialCapacity);
786 this.name = name;
787 }
788
789 public StrictMap(String name) {
790 super();
791 this.name = name;
792 }
793
794 public StrictMap(String name, Map<String, ? extends V> m) {
795 super(m);
796 this.name = name;
797 }
798
799 @SuppressWarnings("unchecked")
800 public V put(String key, V value) {
801 if (containsKey(key)) {
802 throw new IllegalArgumentException(name + " already contains value for " + key);
803 }
804 if (key.contains(".")) {
805 final String shortKey = getShortName(key);
806 if (super.get(shortKey) == null) {
807 super.put(shortKey, value);
808 } else {
809 super.put(shortKey, (V) new Ambiguity(shortKey));
810 }
811 }
812 return super.put(key, value);
813 }
814
815 public V get(Object key) {
816 V value = super.get(key);
817 if (value == null) {
818 throw new IllegalArgumentException(name + " does not contain value for " + key);
819 }
820 if (value instanceof Ambiguity) {
821 throw new IllegalArgumentException(((Ambiguity) value).getSubject() + " is ambiguous in " + name
822 + " (try using the full name including the namespace, or rename one of the entries)");
823 }
824 return value;
825 }
826
827 private String getShortName(String key) {
828 final String[] keyparts = key.split("\\.");
829 return keyparts[keyparts.length - 1];
830 }
831
832 protected static class Ambiguity {
833 private String subject;
834
835 public Ambiguity(String subject) {
836 this.subject = subject;
837 }
838
839 public String getSubject() {
840 return subject;
841 }
842 }
843 }
844
845 }