001    package com.mockrunner.jdbc;
002    
003    import java.util.ArrayList;
004    import java.util.HashMap;
005    import java.util.List;
006    import java.util.Map;
007    
008    import com.mockrunner.util.common.ArrayUtil;
009    
010    /**
011     * Abstract base class for all statement types
012     * that support out parameters, i.e. <code>CallableStatement</code>.
013     */
014    public abstract class AbstractOutParameterResultSetHandler extends AbstractParameterResultSetHandler
015    {
016        private Map globalOutParameter;
017        private Map outParameterForStatement = new HashMap();
018        private Map outParameterForStatementParameters = new HashMap();
019        
020        /**
021         * Returns the first out parameter <code>Map</code> that matches 
022         * the specified SQL string.
023         * Please note that you can modify the match parameters with 
024         * {@link #setCaseSensitive}, {@link #setExactMatch} and 
025         * {@link #setUseRegularExpressions}.
026         * @param sql the SQL string
027         * @return the corresponding out parameter <code>Map</code>
028         */
029        public Map getOutParameter(String sql)
030        {
031            SQLStatementMatcher matcher = new SQLStatementMatcher(getCaseSensitive(), getExactMatch(), getUseRegularExpressions());
032            List list = matcher.getMatchingObjects(outParameterForStatement, sql, true, true);
033            if(null != list && list.size() > 0)
034            {
035                return (Map)list.get(0);
036            }
037            return null;
038        }
039        
040        /**
041         * Returns the first out parameter <code>Map</code> that matches 
042         * the specified SQL string and the specified parameters. 
043         * PPlease note that you can modify the match parameters with 
044         * {@link #setCaseSensitive}, {@link #setExactMatch} and 
045         * {@link #setUseRegularExpressions} and the match parameters for the 
046         * specified parameter list with {@link #setExactMatchParameter}.
047         * @param sql the SQL string
048         * @param parameters the parameters
049         * @return the corresponding out parameter <code>Map</code>
050         */
051        public Map getOutParameter(String sql, Map parameters)
052        {
053            SQLStatementMatcher matcher = new SQLStatementMatcher(getCaseSensitive(), getExactMatch(), getUseRegularExpressions());
054            List list = matcher.getMatchingObjects(outParameterForStatementParameters, sql, true, true);
055            for(int ii = 0; ii < list.size(); ii++)
056            {
057                MockOutParameterWrapper wrapper = (MockOutParameterWrapper)list.get(ii);
058                if(doParameterMatch(wrapper.getParamters(), parameters))
059                {
060                    return wrapper.getOutParameter();
061                }
062            }
063            return null;
064        }
065        
066        /**
067         * Clears the out parameters.
068         */
069        public void clearOutParameter()
070        {
071            outParameterForStatement.clear();
072            outParameterForStatementParameters.clear();
073        }
074        
075        /**
076         * Returns the global out parameter <code>Map</code>.
077         * The statement takes the global global out parameter 
078         * <code>Map</code> if no out parameter <code>Map</code> 
079         * can be found for the current SQL string.
080         * @return the global out parameter <code>Map</code>
081         */
082        public Map getGlobalOutParameter()
083        {
084            return globalOutParameter;
085        }
086        
087        /**
088         * Prepares the global out parameter <code>Map</code>.
089         * The statement takes the global global out parameter 
090         * <code>Map</code> if no out parameter <code>Map</code> 
091         * can be found for the current SQL string.
092         * @param outParameters the global out parameter <code>Map</code>
093         */
094        public void prepareGlobalOutParameter(Map outParameters)
095        {
096            globalOutParameter = new HashMap(outParameters);
097        }
098        
099        /**
100         * Prepare an out parameter <code>Map</code> for a specified 
101         * SQL string.
102         * Please note that you can modify the match parameters with 
103         * {@link #setCaseSensitive}, {@link #setExactMatch} and 
104         * {@link #setUseRegularExpressions}.
105         * @param sql the SQL string
106         * @param outParameters the out parameter <code>Map</code>
107         */
108        public void prepareOutParameter(String sql, Map outParameters)
109        {
110            outParameterForStatement.put(sql, new HashMap(outParameters));
111        }
112        
113        /**
114         * Prepare an out parameter <code>Map</code> for a specified SQL string and
115         * the specified parameters. The specified parameters array
116         * must contain the parameters in the correct order starting with 0 as
117         * the first parameter. Please keep in mind that parameters in
118         * <code>CallableStatement</code> objects start with 1 as the first
119         * parameter. So <code>parameters[0]</code> maps to the
120         * parameter with index 1.
121         * Please note that you can modify the match parameters with 
122         * {@link #setCaseSensitive}, {@link #setExactMatch} and 
123         * {@link #setUseRegularExpressions} and the match parameters for the 
124         * specified parameter list with {@link #setExactMatchParameter}.
125         * @param sql the SQL string
126         * @param outParameters the corresponding out parameter <code>Map</code>
127         * @param parameters the parameters
128         */
129        public void prepareOutParameter(String sql, Map outParameters, Object[] parameters)
130        {
131            prepareOutParameter(sql, outParameters, ArrayUtil.getListFromObjectArray(parameters));
132        }
133        
134        /**
135         * Prepare an out parameter <code>Map</code> for a specified SQL string and
136         * the specified parameters. The specified parameters array
137         * must contain the parameters in the correct order starting with 0 as
138         * the first parameter. Please keep in mind that parameters in
139         * <code>CallableStatement</code> objects start with 1 as the first
140         * parameter. So <code>parameters.get(0)</code> maps to the
141         * parameter with index 1.
142         * Please note that you can modify the match parameters with 
143         * {@link #setCaseSensitive}, {@link #setExactMatch} and 
144         * {@link #setUseRegularExpressions} and the match parameters for the 
145         * specified parameter list with {@link #setExactMatchParameter}.
146         * @param sql the SQL string
147         * @param outParameters the corresponding out parameter <code>Map</code>
148         * @param parameters the parameters
149         */
150        public void prepareOutParameter(String sql, Map outParameters, List parameters)
151        {
152            Map params = new HashMap();
153            for(int ii = 0; ii < parameters.size(); ii++)
154            {
155                params.put(new Integer(ii + 1), parameters.get(ii));
156            }
157            prepareOutParameter(sql, outParameters,  params);
158        }
159        
160        /**
161         * Prepare an out parameter <code>Map</code> for a specified SQL string
162         * and the specified parameters. The specified parameters <code>Map</code>
163         * must contain the parameters by mapping <code>Integer</code> or
164         * <code>String</code> objects to the corresponding parameter. 
165         * An <code>Integer</code> object is the index of the parameter.
166         * A <code>String</code> is the name of the parameter.
167         * Please note that you can modify the match parameters with 
168         * {@link #setCaseSensitive}, {@link #setExactMatch} and 
169         * {@link #setUseRegularExpressions} and the match parameters for the 
170         * specified parameter list with {@link #setExactMatchParameter}.
171         * @param sql the SQL string
172         * @param outParameters the corresponding out parameter <code>Map</code>
173         * @param parameters the parameters
174         */
175        public void prepareOutParameter(String sql, Map outParameters, Map parameters)
176        {
177            List list = (List)outParameterForStatementParameters.get(sql);
178            if(null == list)
179            {
180                list = new ArrayList();
181                outParameterForStatementParameters.put(sql, list);
182            }
183            list.add(new MockOutParameterWrapper(new HashMap(outParameters), parameters));
184        }
185        
186        private class MockOutParameterWrapper
187        {
188            private Map outParameter;
189            private Map parameters;
190    
191            public MockOutParameterWrapper(Map outParameter, Map parameters)
192            {
193                this.outParameter = outParameter;
194                this.parameters = parameters;
195            }
196    
197            public Map getParamters()
198            {
199                return parameters;
200            }
201    
202            public Map getOutParameter()
203            {
204                return outParameter;
205            }
206        }
207    }