View Javadoc
1   /*
2    * Copyright 2004-2022 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.exchange;
17  
18  import com.ibatis.sqlmap.engine.accessplan.AccessPlan;
19  import com.ibatis.sqlmap.engine.accessplan.AccessPlanFactory;
20  import com.ibatis.sqlmap.engine.mapping.parameter.ParameterMap;
21  import com.ibatis.sqlmap.engine.mapping.parameter.ParameterMapping;
22  import com.ibatis.sqlmap.engine.mapping.result.ResultMap;
23  import com.ibatis.sqlmap.engine.mapping.result.ResultMapping;
24  import com.ibatis.sqlmap.engine.mapping.result.ResultObjectFactoryUtil;
25  import com.ibatis.sqlmap.engine.scope.ErrorContext;
26  import com.ibatis.sqlmap.engine.scope.StatementScope;
27  
28  import java.util.ArrayList;
29  import java.util.List;
30  import java.util.Map;
31  
32  /**
33   * DataExchange implementation for beans.
34   */
35  public class JavaBeanDataExchange extends BaseDataExchange implements DataExchange {
36  
37    /** The Constant NO_DATA. */
38    private static final Object[] NO_DATA = new Object[0];
39  
40    /** The result plan. */
41    private AccessPlan resultPlan;
42  
43    /** The parameter plan. */
44    private AccessPlan parameterPlan;
45  
46    /** The out param plan. */
47    private AccessPlan outParamPlan;
48  
49    /**
50     * Instantiates a new java bean data exchange.
51     *
52     * @param dataExchangeFactory
53     *          the data exchange factory
54     */
55    protected JavaBeanDataExchange(DataExchangeFactory dataExchangeFactory) {
56      super(dataExchangeFactory);
57    }
58  
59    /**
60     * Initializes the data exchange instance.
61     *
62     * @param properties
63     *          the properties
64     */
65    public void initialize(Map properties) {
66      Object map = properties.get("map");
67      if (map instanceof ParameterMap) {
68        ParameterMap parameterMap = (ParameterMap) map;
69        if (parameterMap != null) {
70          ParameterMapping[] parameterMappings = parameterMap.getParameterMappings();
71          String[] parameterPropNames = new String[parameterMappings.length];
72          for (int i = 0; i < parameterPropNames.length; i++) {
73            parameterPropNames[i] = parameterMappings[i].getPropertyName();
74          }
75          parameterPlan = AccessPlanFactory.getAccessPlan(parameterMap.getParameterClass(), parameterPropNames);
76  
77          // OUTPUT PARAMS
78          List outParamList = new ArrayList();
79          for (int i = 0; i < parameterPropNames.length; i++) {
80            if (parameterMappings[i].isOutputAllowed()) {
81              outParamList.add(parameterMappings[i].getPropertyName());
82            }
83          }
84          String[] outParams = (String[]) outParamList.toArray(new String[outParamList.size()]);
85          outParamPlan = AccessPlanFactory.getAccessPlan(parameterMap.getParameterClass(), outParams);
86        }
87  
88      } else if (map instanceof ResultMap) {
89        ResultMap resultMap = (ResultMap) map;
90        if (resultMap != null) {
91          ResultMapping[] resultMappings = resultMap.getResultMappings();
92          String[] resultPropNames = new String[resultMappings.length];
93          for (int i = 0; i < resultPropNames.length; i++) {
94            resultPropNames[i] = resultMappings[i].getPropertyName();
95          }
96          resultPlan = AccessPlanFactory.getAccessPlan(resultMap.getResultClass(), resultPropNames);
97        }
98      }
99    }
100 
101   public Object[] getData(StatementScope statementScope, ParameterMap parameterMap, Object parameterObject) {
102     if (parameterPlan != null) {
103       return parameterPlan.getProperties(parameterObject);
104     } else {
105       return NO_DATA;
106     }
107   }
108 
109   public Object setData(StatementScope statementScope, ResultMap resultMap, Object resultObject, Object[] values) {
110     if (resultPlan != null) {
111       Object object = resultObject;
112 
113       ErrorContext errorContext = statementScope.getErrorContext();
114 
115       if (object == null) {
116         errorContext.setMoreInfo("The error occured while instantiating the result object");
117         try {
118           object = ResultObjectFactoryUtil.createObjectThroughFactory(resultMap.getResultClass());
119         } catch (Exception e) {
120           throw new RuntimeException("JavaBeansDataExchange could not instantiate result class.  Cause: " + e, e);
121         }
122       }
123       errorContext.setMoreInfo("The error happened while setting a property on the result object.");
124       resultPlan.setProperties(object, values);
125       return object;
126     } else {
127       return null;
128     }
129   }
130 
131   // Bug ibatis-12
132   public Object setData(StatementScope statementScope, ParameterMap parameterMap, Object parameterObject,
133       Object[] values) {
134     if (outParamPlan != null) {
135       Object object = parameterObject;
136       if (object == null) {
137         try {
138           object = ResultObjectFactoryUtil.createObjectThroughFactory(parameterMap.getParameterClass());
139         } catch (Exception e) {
140           throw new RuntimeException("JavaBeansDataExchange could not instantiate parameter class. Cause: " + e, e);
141         }
142       }
143       values = getOutputParamValues(parameterMap.getParameterMappings(), values);
144       outParamPlan.setProperties(object, values);
145       return object;
146     } else {
147       return null;
148     }
149   }
150 
151   /**
152    * Gets the output param values.
153    *
154    * @param mappings
155    *          the mappings
156    * @param values
157    *          the values
158    *
159    * @return the output param values
160    */
161   private Object[] getOutputParamValues(ParameterMapping[] mappings, Object[] values) {
162     List outParamValues = new ArrayList();
163     for (int i = 0; i < mappings.length; i++) {
164       if (mappings[i].isOutputAllowed()) {
165         outParamValues.add(values[i]);
166       }
167     }
168     return outParamValues.toArray();
169   }
170 
171 }