1 package com.ibatis.sqlmap.engine.mapping.parameter; 2 3 import com.ibatis.common.beans.Probe; 4 import com.ibatis.common.beans.ProbeFactory; 5 import com.ibatis.common.resources.Resources; 6 import com.ibatis.sqlmap.client.SqlMapException; 7 import com.ibatis.sqlmap.client.extensions.TypeHandlerCallback; 8 import com.ibatis.sqlmap.engine.mapping.sql.SqlText; 9 import com.ibatis.sqlmap.engine.type.CustomTypeHandler; 10 import com.ibatis.sqlmap.engine.type.DomTypeMarker; 11 import com.ibatis.sqlmap.engine.type.TypeHandler; 12 import com.ibatis.sqlmap.engine.type.TypeHandlerFactory; 13 14 import java.util.ArrayList ; 15 import java.util.List ; 16 import java.util.StringTokenizer ; 17 18 public class InlineParameterMapParser { 19 20 private static final Probe PROBE = ProbeFactory.getProbe(); 21 private static final String PARAMETER_TOKEN = "#"; 22 private static final String PARAM_DELIM = ":"; 23 24 public SqlText parseInlineParameterMap(TypeHandlerFactory typeHandlerFactory, String sqlStatement) { 25 return parseInlineParameterMap(typeHandlerFactory, sqlStatement, null); 26 } 27 28 public SqlText parseInlineParameterMap(TypeHandlerFactory typeHandlerFactory, String sqlStatement, Class parameterClass) { 29 30 String newSql = sqlStatement; 31 32 List mappingList = new ArrayList (); 33 34 StringTokenizer parser = new StringTokenizer (sqlStatement, PARAMETER_TOKEN, true); 35 StringBuffer newSqlBuffer = new StringBuffer (); 36 37 String token = null; 38 String lastToken = null; 39 while (parser.hasMoreTokens()) { 40 token = parser.nextToken(); 41 if (PARAMETER_TOKEN.equals(lastToken)) { 42 if (PARAMETER_TOKEN.equals(token)) { 43 newSqlBuffer.append(PARAMETER_TOKEN); 44 token = null; 45 } else { 46 ParameterMapping mapping = null; 47 if (token.indexOf(PARAM_DELIM) > -1) { 48 mapping = oldParseMapping(token, parameterClass, typeHandlerFactory); 49 } else { 50 mapping = newParseMapping(token, parameterClass, typeHandlerFactory); 51 } 52 53 mappingList.add(mapping); 54 newSqlBuffer.append("?"); 55 token = parser.nextToken(); 56 if (!PARAMETER_TOKEN.equals(token)) { 57 throw new SqlMapException("Unterminated inline parameter in mapped statement (" + "statement.getId()" + ")."); 58 } 59 token = null; 60 } 61 } else { 62 if (!PARAMETER_TOKEN.equals(token)) { 63 newSqlBuffer.append(token); 64 } 65 } 66 67 lastToken = token; 68 } 69 70 newSql = newSqlBuffer.toString(); 71 72 ParameterMapping[] mappingArray = (ParameterMapping[]) mappingList.toArray(new ParameterMapping[mappingList.size()]); 73 74 SqlText sqlText = new SqlText(); 75 sqlText.setText(newSql); 76 sqlText.setParameterMappings(mappingArray); 77 return sqlText; 78 } 79 80 private ParameterMapping newParseMapping(String token, Class parameterClass, TypeHandlerFactory typeHandlerFactory) { 81 BasicParameterMapping mapping = new BasicParameterMapping(); 82 83 85 StringTokenizer paramParser = new StringTokenizer (token, "=,", false); 86 mapping.setPropertyName(paramParser.nextToken()); 87 88 while (paramParser.hasMoreTokens()) { 89 String field = paramParser.nextToken(); 90 if (paramParser.hasMoreTokens()) { 91 String value = paramParser.nextToken(); 92 if ("javaType".equals(field)) { 93 value = typeHandlerFactory.resolveAlias(value); 94 mapping.setJavaTypeName(value); 95 } else if ("jdbcType".equals(field)) { 96 mapping.setJdbcTypeName(value); 97 } else if ("mode".equals(field)) { 98 mapping.setMode(value); 99 } else if ("nullValue".equals(field)) { 100 mapping.setNullValue(value); 101 } else if ("handler".equals(field)) { 102 try { 103 value = typeHandlerFactory.resolveAlias(value); 104 mapping.setTypeHandler(new CustomTypeHandler((TypeHandlerCallback) Resources.classForName(value).newInstance())); 105 } catch (Exception e) { 106 throw new SqlMapException("Error loading class specified by handler field in " + token + ". Cause: " + e, e); 107 } 108 } else { 109 throw new SqlMapException("Unrecognized parameter mapping field: '" + field + "' in " + token); 110 } 111 } else { 112 throw new SqlMapException("Incorrect inline parameter map format (missmatched name=value pairs): " + token); 113 } 114 } 115 116 if (mapping.getTypeHandler() == null) { 117 TypeHandler handler; 118 if (parameterClass == null) { 119 handler = typeHandlerFactory.getUnkownTypeHandler(); 120 } else { 121 handler = resolveTypeHandler(typeHandlerFactory, parameterClass, mapping.getPropertyName(), mapping.getJavaTypeName(), mapping.getJdbcTypeName()); 122 } 123 mapping.setTypeHandler(handler); 124 } 125 126 return mapping; 127 } 128 129 private ParameterMapping oldParseMapping(String token, Class parameterClass, TypeHandlerFactory typeHandlerFactory) { 130 BasicParameterMapping mapping = new BasicParameterMapping(); 131 if (token.indexOf(PARAM_DELIM) > -1) { 132 StringTokenizer paramParser = new StringTokenizer (token, PARAM_DELIM, true); 133 int n1 = paramParser.countTokens(); 134 if (n1 == 3) { 135 String name = paramParser.nextToken(); 136 paramParser.nextToken(); String type = paramParser.nextToken(); 138 mapping.setPropertyName(name); 139 mapping.setJdbcTypeName(type); 140 TypeHandler handler; 141 if (parameterClass == null) { 142 handler = typeHandlerFactory.getUnkownTypeHandler(); 143 } else { 144 handler = resolveTypeHandler(typeHandlerFactory, parameterClass, name, null, type); 145 } 146 mapping.setTypeHandler(handler); 147 return mapping; 148 } else if (n1 >= 5) { 149 String name = paramParser.nextToken(); 150 paramParser.nextToken(); String type = paramParser.nextToken(); 152 paramParser.nextToken(); String nullValue = paramParser.nextToken(); 154 while (paramParser.hasMoreTokens()) { 155 nullValue = nullValue + paramParser.nextToken(); 156 } 157 mapping.setPropertyName(name); 158 mapping.setJdbcTypeName(type); 159 mapping.setNullValue(nullValue); 160 TypeHandler handler; 161 if (parameterClass == null) { 162 handler = typeHandlerFactory.getUnkownTypeHandler(); 163 } else { 164 handler = resolveTypeHandler(typeHandlerFactory, parameterClass, name, null, type); 165 } 166 mapping.setTypeHandler(handler); 167 return mapping; 168 } else { 169 throw new SqlMapException("Incorrect inline parameter map format: " + token); 170 } 171 } else { 172 mapping.setPropertyName(token); 173 TypeHandler handler; 174 if (parameterClass == null) { 175 handler = typeHandlerFactory.getUnkownTypeHandler(); 176 } else { 177 handler = resolveTypeHandler(typeHandlerFactory, parameterClass, token, null, null); 178 } 179 mapping.setTypeHandler(handler); 180 return mapping; 181 } 182 } 183 184 private TypeHandler resolveTypeHandler(TypeHandlerFactory typeHandlerFactory, Class clazz, String propertyName, String javaType, String jdbcType) { 185 TypeHandler handler = null; 186 if (clazz == null) { 187 handler = typeHandlerFactory.getUnkownTypeHandler(); 189 } else if (DomTypeMarker.class.isAssignableFrom(clazz)) { 190 handler = typeHandlerFactory.getTypeHandler(String .class, jdbcType); 192 } else if (java.util.Map .class.isAssignableFrom(clazz)) { 193 if (javaType == null) { 195 handler = typeHandlerFactory.getUnkownTypeHandler(); } else { 197 try { 198 javaType = typeHandlerFactory.resolveAlias(javaType); 199 Class javaClass = Resources.classForName(javaType); 200 handler = typeHandlerFactory.getTypeHandler(javaClass, jdbcType); 201 } catch (Exception e) { 202 throw new SqlMapException("Error. Could not set TypeHandler. Cause: " + e, e); 203 } 204 } 205 } else if (typeHandlerFactory.getTypeHandler(clazz, jdbcType) != null) { 206 handler = typeHandlerFactory.getTypeHandler(clazz, jdbcType); 208 } else { 209 if (javaType == null) { 211 212 Class type = PROBE.getPropertyTypeForGetter(clazz, propertyName); 213 handler = typeHandlerFactory.getTypeHandler(type, jdbcType); 214 215 } else { 216 try { 217 javaType = typeHandlerFactory.resolveAlias(javaType); 218 Class javaClass = Resources.classForName(javaType); 219 handler = typeHandlerFactory.getTypeHandler(javaClass, jdbcType); 220 } catch (Exception e) { 221 throw new SqlMapException("Error. Could not set TypeHandler. Cause: " + e, e); 222 } 223 } 224 } 225 return handler; 226 } 227 228 229 } 230 | Popular Tags |