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