View Javadoc
1   /*
2    * Copyright 2004-2023 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 com.ibatis.sqlmap.engine.config;
17  
18  import com.ibatis.sqlmap.client.extensions.TypeHandlerCallback;
19  import com.ibatis.sqlmap.engine.impl.SqlMapClientImpl;
20  import com.ibatis.sqlmap.engine.impl.SqlMapExecutorDelegate;
21  import com.ibatis.sqlmap.engine.mapping.result.Discriminator;
22  import com.ibatis.sqlmap.engine.mapping.result.ResultMap;
23  import com.ibatis.sqlmap.engine.mapping.result.ResultMapping;
24  import com.ibatis.sqlmap.engine.scope.ErrorContext;
25  import com.ibatis.sqlmap.engine.type.CustomTypeHandler;
26  import com.ibatis.sqlmap.engine.type.TypeHandler;
27  import com.ibatis.sqlmap.engine.type.TypeHandlerFactory;
28  
29  import java.util.ArrayList;
30  import java.util.Iterator;
31  import java.util.List;
32  import java.util.StringTokenizer;
33  
34  /**
35   * The Class ResultMapConfig.
36   */
37  public class ResultMapConfig {
38  
39    /** The config. */
40    private SqlMapConfiguration config;
41  
42    /** The error context. */
43    private ErrorContext errorContext;
44  
45    /** The client. */
46    private SqlMapClientImpl client;
47  
48    /** The delegate. */
49    private SqlMapExecutorDelegate delegate;
50  
51    /** The type handler factory. */
52    private TypeHandlerFactory typeHandlerFactory;
53  
54    /** The result map. */
55    private ResultMap resultMap;
56  
57    /** The result mapping list. */
58    private List resultMappingList;
59  
60    /** The result mapping index. */
61    private int resultMappingIndex;
62  
63    /** The discriminator. */
64    private Discriminator discriminator;
65  
66    /**
67     * Instantiates a new result map config.
68     *
69     * @param config
70     *          the config
71     * @param id
72     *          the id
73     * @param resultClass
74     *          the result class
75     * @param groupBy
76     *          the group by
77     * @param extendsResultMap
78     *          the extends result map
79     * @param xmlName
80     *          the xml name
81     */
82    ResultMapConfig(SqlMapConfiguration config, String id, Class resultClass, String groupBy, String extendsResultMap,
83        String xmlName) {
84      this.config = config;
85      this.errorContext = config.getErrorContext();
86      this.client = config.getClient();
87      this.delegate = config.getDelegate();
88      this.typeHandlerFactory = config.getTypeHandlerFactory();
89      this.resultMap = new ResultMap(client.getDelegate());
90      this.resultMappingList = new ArrayList();
91      errorContext.setActivity("building a result map");
92      errorContext.setObjectId(id + " result map");
93      resultMap.setId(id);
94      resultMap.setXmlName(xmlName);
95      resultMap.setResource(errorContext.getResource());
96      if (groupBy != null && groupBy.length() > 0) {
97        StringTokenizer parser = new StringTokenizer(groupBy, ", ", false);
98        while (parser.hasMoreTokens()) {
99          resultMap.addGroupByProperty(parser.nextToken());
100       }
101     }
102     resultMap.setResultClass(resultClass);
103     errorContext.setMoreInfo("Check the extended result map.");
104     if (extendsResultMap != null) {
105       ResultMap extendedResultMap = (ResultMap) client.getDelegate().getResultMap(extendsResultMap);
106       ResultMapping[] resultMappings = extendedResultMap.getResultMappings();
107       for (int i = 0; i < resultMappings.length; i++) {
108         resultMappingList.add(resultMappings[i]);
109       }
110       List nestedResultMappings = extendedResultMap.getNestedResultMappings();
111       if (nestedResultMappings != null) {
112         Iterator iter = nestedResultMappings.iterator();
113         while (iter.hasNext()) {
114           resultMap.addNestedResultMappings((ResultMapping) iter.next());
115         }
116       }
117       if (groupBy == null || groupBy.length() == 0) {
118         if (extendedResultMap.hasGroupBy()) {
119           Iterator i = extendedResultMap.groupByProps();
120           while (i.hasNext()) {
121             resultMap.addGroupByProperty((String) i.next());
122           }
123         }
124       }
125     }
126     errorContext.setMoreInfo("Check the result mappings.");
127     resultMappingIndex = resultMappingList.size();
128     resultMap.setResultMappingList(resultMappingList);
129     client.getDelegate().addResultMap(resultMap);
130   }
131 
132   /**
133    * Sets the discriminator.
134    *
135    * @param columnName
136    *          the column name
137    * @param columnIndex
138    *          the column index
139    * @param javaClass
140    *          the java class
141    * @param jdbcType
142    *          the jdbc type
143    * @param nullValue
144    *          the null value
145    * @param typeHandlerImpl
146    *          the type handler impl
147    */
148   public void setDiscriminator(String columnName, Integer columnIndex, Class javaClass, String jdbcType,
149       String nullValue, Object typeHandlerImpl) {
150     TypeHandler handler;
151     if (typeHandlerImpl != null) {
152       if (typeHandlerImpl instanceof TypeHandlerCallback) {
153         handler = new CustomTypeHandler((TypeHandlerCallback) typeHandlerImpl);
154       } else if (typeHandlerImpl instanceof TypeHandler) {
155         handler = (TypeHandler) typeHandlerImpl;
156       } else {
157         throw new RuntimeException("The class '' is not a valid implementation of TypeHandler or TypeHandlerCallback");
158       }
159     } else {
160       handler = config.resolveTypeHandler(client.getDelegate().getTypeHandlerFactory(), resultMap.getResultClass(), "",
161           javaClass, jdbcType, true);
162     }
163     ResultMapping mapping = new ResultMapping();
164     mapping.setColumnName(columnName);
165     mapping.setJdbcTypeName(jdbcType);
166     mapping.setTypeHandler(handler);
167     mapping.setNullValue(nullValue);
168     mapping.setJavaType(javaClass);
169     if (columnIndex != null) {
170       mapping.setColumnIndex(columnIndex.intValue());
171     }
172     discriminator = new Discriminator(delegate, mapping);
173     resultMap.setDiscriminator(discriminator);
174   }
175 
176   /**
177    * Adds the discriminator sub map.
178    *
179    * @param value
180    *          the value
181    * @param resultMap
182    *          the result map
183    */
184   public void addDiscriminatorSubMap(Object value, String resultMap) {
185     if (discriminator == null) {
186       throw new RuntimeException("The discriminator is null, but somehow a subMap was reached.  This is a bug.");
187     }
188     discriminator.addSubMap(value.toString(), resultMap);
189   }
190 
191   /**
192    * Adds the result mapping.
193    *
194    * @param propertyName
195    *          the property name
196    * @param columnName
197    *          the column name
198    * @param columnIndex
199    *          the column index
200    * @param javaClass
201    *          the java class
202    * @param jdbcType
203    *          the jdbc type
204    * @param nullValue
205    *          the null value
206    * @param notNullColumn
207    *          the not null column
208    * @param statementName
209    *          the statement name
210    * @param resultMapName
211    *          the result map name
212    * @param impl
213    *          the impl
214    */
215   public void addResultMapping(String propertyName, String columnName, Integer columnIndex, Class javaClass,
216       String jdbcType, String nullValue, String notNullColumn, String statementName, String resultMapName,
217       Object impl) {
218     errorContext.setObjectId(propertyName + " mapping of the " + resultMap.getId() + " result map");
219     TypeHandler handler;
220     if (impl != null) {
221       if (impl instanceof TypeHandlerCallback) {
222         handler = new CustomTypeHandler((TypeHandlerCallback) impl);
223       } else if (impl instanceof TypeHandler) {
224         handler = (TypeHandler) impl;
225       } else {
226         throw new RuntimeException(
227             "The class '" + impl + "' is not a valid implementation of TypeHandler or TypeHandlerCallback");
228       }
229     } else {
230       handler = config.resolveTypeHandler(client.getDelegate().getTypeHandlerFactory(), resultMap.getResultClass(),
231           propertyName, javaClass, jdbcType, true);
232     }
233     ResultMapping mapping = new ResultMapping();
234     mapping.setPropertyName(propertyName);
235     mapping.setColumnName(columnName);
236     mapping.setJdbcTypeName(jdbcType);
237     mapping.setTypeHandler(handler);
238     mapping.setNullValue(nullValue);
239     mapping.setNotNullColumn(notNullColumn);
240     mapping.setStatementName(statementName);
241     mapping.setNestedResultMapName(resultMapName);
242     if (resultMapName != null && resultMapName.length() > 0) {
243       resultMap.addNestedResultMappings(mapping);
244     }
245     mapping.setJavaType(javaClass);
246     if (columnIndex != null) {
247       mapping.setColumnIndex(columnIndex.intValue());
248     } else {
249       resultMappingIndex++;
250       mapping.setColumnIndex(resultMappingIndex);
251     }
252     resultMappingList.add(mapping);
253     resultMap.setResultMappingList(resultMappingList);
254   }
255 
256 }