1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.apache.ibatis.scripting.xmltags;
17
18 import java.util.HashMap;
19 import java.util.Map;
20 import java.util.StringJoiner;
21
22 import ognl.OgnlContext;
23 import ognl.OgnlRuntime;
24 import ognl.PropertyAccessor;
25
26 import org.apache.ibatis.reflection.MetaObject;
27 import org.apache.ibatis.session.Configuration;
28
29
30
31
32 public class DynamicContext {
33
34 public static final String PARAMETER_OBJECT_KEY = "_parameter";
35 public static final String DATABASE_ID_KEY = "_databaseId";
36
37 static {
38 OgnlRuntime.setPropertyAccessor(ContextMap.class, new ContextAccessor());
39 }
40
41 private final ContextMap bindings;
42 private final StringJoiner sqlBuilder = new StringJoiner(" ");
43 private int uniqueNumber;
44
45 public DynamicContext(Configuration configuration, Object parameterObject) {
46 if (parameterObject != null && !(parameterObject instanceof Map)) {
47 MetaObject metaObject = configuration.newMetaObject(parameterObject);
48 boolean existsTypeHandler = configuration.getTypeHandlerRegistry().hasTypeHandler(parameterObject.getClass());
49 bindings = new ContextMap(metaObject, existsTypeHandler);
50 } else {
51 bindings = new ContextMap(null, false);
52 }
53 bindings.put(PARAMETER_OBJECT_KEY, parameterObject);
54 bindings.put(DATABASE_ID_KEY, configuration.getDatabaseId());
55 }
56
57 public Map<String, Object> getBindings() {
58 return bindings;
59 }
60
61 public void bind(String name, Object value) {
62 bindings.put(name, value);
63 }
64
65 public void appendSql(String sql) {
66 sqlBuilder.add(sql);
67 }
68
69 public String getSql() {
70 return sqlBuilder.toString().trim();
71 }
72
73 public int getUniqueNumber() {
74 return uniqueNumber++;
75 }
76
77 static class ContextMap extends HashMap<String, Object> {
78 private static final long serialVersionUID = 2977601501966151582L;
79 private final MetaObject parameterMetaObject;
80 private final boolean fallbackParameterObject;
81
82 public ContextMap(MetaObject parameterMetaObject, boolean fallbackParameterObject) {
83 this.parameterMetaObject = parameterMetaObject;
84 this.fallbackParameterObject = fallbackParameterObject;
85 }
86
87 @Override
88 public Object get(Object key) {
89 String strKey = (String) key;
90 if (super.containsKey(strKey)) {
91 return super.get(strKey);
92 }
93
94 if (parameterMetaObject == null) {
95 return null;
96 }
97
98 if (fallbackParameterObject && !parameterMetaObject.hasGetter(strKey)) {
99 return parameterMetaObject.getOriginalObject();
100 }
101
102 return parameterMetaObject.getValue(strKey);
103 }
104 }
105
106 static class ContextAccessor implements PropertyAccessor {
107
108 @Override
109 public Object getProperty(OgnlContext context, Object target, Object name) {
110 Map map = (Map) target;
111
112 Object result = map.get(name);
113 if (map.containsKey(name) || result != null) {
114 return result;
115 }
116
117 Object parameterObject = map.get(PARAMETER_OBJECT_KEY);
118 if (parameterObject instanceof Map) {
119 return ((Map) parameterObject).get(name);
120 }
121
122 return null;
123 }
124
125 @Override
126 public void setProperty(OgnlContext context, Object target, Object name, Object value) {
127 Map<Object, Object> map = (Map<Object, Object>) target;
128 map.put(name, value);
129 }
130
131 @Override
132 public String getSourceAccessor(OgnlContext arg0, Object arg1, Object arg2) {
133 return null;
134 }
135
136 @Override
137 public String getSourceSetter(OgnlContext arg0, Object arg1, Object arg2) {
138 return null;
139 }
140 }
141 }