View Javadoc
1   package org.synchronoss.cpo.jdbc;
2   
3   /*-
4    * [[
5    * jdbc
6    * ==
7    * Copyright (C) 2003 - 2026 Exaxis LLC, Synchronoss Technologies Inc
8    * ==
9    * This program is free software: you can redistribute it and/or modify
10   * it under the terms of the GNU Lesser General Public License as
11   * published by the Free Software Foundation, either version 3 of the
12   * License, or (at your option) any later version.
13   *
14   * This program is distributed in the hope that it will be useful,
15   * but WITHOUT ANY WARRANTY; without even the implied warranty of
16   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17   * GNU General Lesser Public License for more details.
18   *
19   * You should have received a copy of the GNU General Lesser Public
20   * License along with this program.  If not, see
21   * <http://www.gnu.org/licenses/lgpl-3.0.html>.
22   * ]]
23   */
24  
25  import java.lang.reflect.InvocationTargetException;
26  import java.sql.CallableStatement;
27  import org.slf4j.Logger;
28  import org.slf4j.LoggerFactory;
29  import org.synchronoss.cpo.core.CpoException;
30  import org.synchronoss.cpo.core.helper.ExceptionHelper;
31  import org.synchronoss.cpo.core.meta.domain.CpoAttribute;
32  import org.synchronoss.cpo.core.transform.CpoTransform;
33  import org.synchronoss.cpo.jdbc.meta.JdbcMethodMapEntry;
34  import org.synchronoss.cpo.jdbc.meta.JdbcMethodMapper;
35  import org.synchronoss.cpo.jdbc.transform.JdbcCpoTransform;
36  
37  /**
38   * Moves a bound attribute's value to or from a JDBC {@link CallableStatement} IN/OUT parameter,
39   * applying any configured {@link JdbcCpoTransform} along the way.
40   *
41   * @author dberry
42   */
43  public class CallableStatementCpoData extends AbstractStatementCpoData {
44  
45    private static final Logger logger = LoggerFactory.getLogger(CallableStatementCpoData.class);
46    private CallableStatement cs = null;
47    JdbcCallableStatementFactory jcsf = null;
48  
49    /**
50     * Constructs a CallableStatementCpoData
51     *
52     * @param cs - The callable statement
53     * @param cpoAttribute - The attribute to add.
54     * @param index - The index of the attribute in the callable statement
55     */
56    public CallableStatementCpoData(CallableStatement cs, CpoAttribute cpoAttribute, int index) {
57      super(cpoAttribute, index);
58      this.cs = cs;
59    }
60  
61    /**
62     * Constructs a CallableStatementCpoData
63     *
64     * @param jcsf - The factory for building the callable statement
65     * @param cpoAttribute - The attribute to add.
66     * @param index - The index of the attribute in the callable statement
67     */
68    public CallableStatementCpoData(
69        JdbcCallableStatementFactory jcsf, CpoAttribute cpoAttribute, int index) {
70      super(cpoAttribute, index);
71      this.jcsf = jcsf;
72    }
73  
74    @Override
75    public Object transformOut(Object attributeObject) throws CpoException {
76      Object retObj = attributeObject;
77      CpoTransform cpoTransform = getCpoAttribute().getCpoTransform();
78  
79      if (cpoTransform != null) {
80        if (cpoTransform instanceof JdbcCpoTransform) {
81          retObj = ((JdbcCpoTransform) cpoTransform).transformOut(jcsf, attributeObject);
82        } else {
83          retObj = cpoTransform.transformOut(attributeObject);
84        }
85      }
86      return retObj;
87    }
88  
89    @Override
90    public Object invokeGetter() throws CpoException {
91      Object javaObject = null;
92      JdbcMethodMapEntry<?, ?> jdbcMethodMapEntry =
93          JdbcMethodMapper.getJavaSqlMethod(getDataGetterReturnType());
94      if (jdbcMethodMapEntry == null) {
95        if (Object.class.isAssignableFrom(getDataGetterReturnType())) {
96          jdbcMethodMapEntry = JdbcMethodMapper.getJavaSqlMethod(Object.class);
97        }
98        if (jdbcMethodMapEntry == null) {
99          throw new CpoException(
100             "Error Retrieving Jdbc Method for type: " + getDataGetterReturnType().getName());
101       }
102     }
103 
104     try {
105       // Get the getter for the Callable Statement
106       switch (jdbcMethodMapEntry.getMethodType()) {
107         case JdbcMethodMapEntry.METHOD_TYPE_BASIC:
108         case JdbcMethodMapEntry.METHOD_TYPE_STREAM:
109         case JdbcMethodMapEntry.METHOD_TYPE_READER:
110           javaObject = jdbcMethodMapEntry.getCsGetter().invoke(cs, getIndex());
111           break;
112         case JdbcMethodMapEntry.METHOD_TYPE_OBJECT:
113         default:
114           javaObject =
115               jdbcMethodMapEntry
116                   .getCsGetter()
117                   .invoke(cs, getIndex(), jdbcMethodMapEntry.getJavaClass());
118           break;
119       }
120       javaObject = transformIn(javaObject);
121     } catch (IllegalAccessException | InvocationTargetException ie) {
122       throw new CpoException("Error Invoking CallableStatement Method: ", ie);
123     }
124 
125     return javaObject;
126   }
127 
128   @Override
129   public void invokeSetter(Object instanceObject) throws CpoException {
130     Logger localLogger =
131         instanceObject == null ? logger : LoggerFactory.getLogger(instanceObject.getClass());
132     CpoAttribute cpoAttribute = getCpoAttribute();
133     Object param = transformOut(cpoAttribute.invokeGetter(instanceObject));
134     // per-attribute bind values are debug detail, not operational info
135     localLogger.debug("{}={}", cpoAttribute.getDataName(), param);
136     JdbcMethodMapEntry<?, ?> jdbcMethodMapEntry = getJdbcMethodMapEntry(instanceObject);
137     try {
138       jdbcMethodMapEntry.getCsSetter().invoke(jcsf.getCallableStatement(), getIndex(), param);
139     } catch (Exception e) {
140       throw new CpoException(
141           "Error Invoking Jdbc Method: "
142               + jdbcMethodMapEntry.getBsSetter().getName()
143               + ":"
144               + ExceptionHelper.getLocalizedMessage(e));
145     }
146   }
147 }