/******************************************************************************* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. *******************************************************************************/ package org.ofbiz.entity.jdbc; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.io.ObjectInputStream; import java.io.Reader; import java.math.BigDecimal; import java.sql.ResultSet; import java.sql.ResultSetMetaData; import java.sql.SQLException; import java.sql.Clob; import java.util.Collection; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import java.util.TreeSet; import javolution.util.FastMap; import org.ofbiz.base.util.Debug; import org.ofbiz.base.util.ObjectType; import org.ofbiz.base.util.UtilValidate; import org.ofbiz.entity.GenericDataSourceException; import org.ofbiz.entity.GenericEntity; import org.ofbiz.entity.GenericEntityException; import org.ofbiz.entity.GenericModelException; import org.ofbiz.entity.GenericNotImplementedException; import org.ofbiz.entity.GenericValue; import org.ofbiz.entity.condition.EntityConditionParam; import org.ofbiz.entity.condition.OrderByList; import org.ofbiz.entity.config.DatasourceInfo; import org.ofbiz.entity.datasource.GenericDAO; import org.ofbiz.entity.model.ModelEntity; import org.ofbiz.entity.model.ModelField; import org.ofbiz.entity.model.ModelFieldType; import org.ofbiz.entity.model.ModelFieldTypeReader; import org.ofbiz.entity.model.ModelKeyMap; import org.ofbiz.entity.model.ModelViewEntity; /** * GenericDAO Utility methods for general tasks * */ public class SqlJdbcUtil { public static final String module = GenericDAO.class.getName(); public static final int CHAR_BUFFER_SIZE = 4096; /** Makes the FROM clause and when necessary the JOIN clause(s) as well */ public static String makeFromClause(ModelEntity modelEntity, DatasourceInfo datasourceInfo) throws GenericEntityException { StringBuffer sql = new StringBuffer(" FROM "); if (modelEntity instanceof ModelViewEntity) { ModelViewEntity modelViewEntity = (ModelViewEntity) modelEntity; if ("ansi".equals(datasourceInfo.joinStyle) || "ansi-no-parenthesis".equals(datasourceInfo.joinStyle)) { boolean useParenthesis = true; if ("ansi-no-parenthesis".equals(datasourceInfo.joinStyle)) { useParenthesis = false; } // FROM clause: in this case will be a bunch of joins that correspond with the view-links // BIG NOTE on the JOIN clauses: the order of joins is determined by the order of the // view-links; for more flexible order we'll have to figure something else out and // extend the DTD for the nested view-link elements or something // At this point it is assumed that in each view-link the left hand alias will // either be the first alias in the series or will already be in a previous // view-link and already be in the big join; SO keep a set of all aliases // in the join so far and if the left entity alias isn't there yet, and this // isn't the first one, throw an exception Set joinedAliasSet = new TreeSet(); // TODO: at view-link read time make sure they are ordered properly so that each // left hand alias after the first view-link has already been linked before StringBuffer openParens = null; if (useParenthesis) openParens = new StringBuffer(); StringBuffer restOfStatement = new StringBuffer(); for (int i = 0; i < modelViewEntity.getViewLinksSize(); i++) { // don't put starting parenthesis if (i > 0 && useParenthesis) openParens.append('('); ModelViewEntity.ModelViewLink viewLink = modelViewEntity.getViewLink(i); ModelEntity linkEntity = modelViewEntity.getMemberModelEntity(viewLink.getEntityAlias()); ModelEntity relLinkEntity = modelViewEntity.getMemberModelEntity(viewLink.getRelEntityAlias()); // ModelViewEntity.ModelMemberEntity linkMemberEntity = modelViewEntity.getMemberModelMemberEntity(viewLink.getEntityAlias()); // ModelViewEntity.ModelMemberEntity relLinkMemberEntity = modelViewEntity.getMemberModelMemberEntity(viewLink.getRelEntityAlias()); if (i == 0) { // this is the first referenced member alias, so keep track of it for future use... restOfStatement.append(makeViewTable(linkEntity, datasourceInfo)); //another possible one that some dbs might need, but not sure of any yet: restOfStatement.append(" AS "); restOfStatement.append(" "); restOfStatement.append(viewLink.getEntityAlias()); joinedAliasSet.add(viewLink.getEntityAlias()); } else { // make sure the left entity alias is already in the join... if (!joinedAliasSet.contains(viewLink.getEntityAlias())) { throw new GenericModelException("Tried to link the " + viewLink.getEntityAlias() + " alias to the " + viewLink.getRelEntityAlias() + " alias of the " + modelViewEntity.getEntityName() + " view-entity, but it is not the first view-link and has not been included in a previous view-link. In other words, the left/main alias isn't connected to the rest of the member-entities yet."); } } // now put the rel (right) entity alias into the set that is in the join joinedAliasSet.add(viewLink.getRelEntityAlias()); if (viewLink.isRelOptional()) { restOfStatement.append(" LEFT OUTER JOIN "); } else { restOfStatement.append(" INNER JOIN "); } restOfStatement.append(makeViewTable(relLinkEntity, datasourceInfo)); //another possible one that some dbs might need, but not sure of any yet: restOfStatement.append(" AS "); restOfStatement.append(" "); restOfStatement.append(viewLink.getRelEntityAlias()); restOfStatement.append(" ON "); StringBuffer condBuffer = new StringBuffer(); for (int j = 0; j < viewLink.getKeyMapsSize(); j++) { ModelKeyMap keyMap = viewLink.getKeyMap(j); ModelField linkField = linkEntity.getField(keyMap.getFieldName()); if (linkField == null) { throw new GenericModelException("Invalid field name in view-link key-map for the " + viewLink.getEntityAlias() + " and the " + viewLink.getRelEntityAlias() + " member-entities of the " + modelViewEntity.getEntityName() + " view-entity; the field [" + keyMap.getFieldName() + "] does not exist on the [" + linkEntity.getEntityName() + "] entity."); } ModelField relLinkField = relLinkEntity.getField(keyMap.getRelFieldName()); if (relLinkField == null) { throw new GenericModelException("Invalid related field name in view-link key-map for the " + viewLink.getEntityAlias() + " and the " + viewLink.getRelEntityAlias() + " member-entities of the " + modelViewEntity.getEntityName() + " view-entity; the field [" + keyMap.getRelFieldName() + "] does not exist on the [" + relLinkEntity.getEntityName() + "] entity."); } if (condBuffer.length() > 0) { condBuffer.append(" AND "); } condBuffer.append(viewLink.getEntityAlias()); condBuffer.append("."); condBuffer.append(filterColName(linkField.getColName())); condBuffer.append(" = "); condBuffer.append(viewLink.getRelEntityAlias()); condBuffer.append("."); condBuffer.append(filterColName(relLinkField.getColName())); } if (condBuffer.length() == 0) { throw new GenericModelException("No view-link/join key-maps found for the " + viewLink.getEntityAlias() + " and the " + viewLink.getRelEntityAlias() + " member-entities of the " + modelViewEntity.getEntityName() + " view-entity."); } restOfStatement.append(condBuffer.toString()); // don't put ending parenthesis if (i < (modelViewEntity.getViewLinksSize() - 1) && useParenthesis) restOfStatement.append(')'); } if (useParenthesis) sql.append(openParens.toString()); sql.append(restOfStatement.toString()); // handle tables not included in view-link Iterator meIter = modelViewEntity.getMemberModelMemberEntities().entrySet().iterator(); boolean fromEmpty = restOfStatement.length() == 0; while (meIter.hasNext()) { Map.Entry entry = (Map.Entry) meIter.next(); ModelEntity fromEntity = modelViewEntity.getMemberModelEntity((String) entry.getKey()); if (!joinedAliasSet.contains((String) entry.getKey())) { if (!fromEmpty) sql.append(", "); fromEmpty = false; sql.append(makeViewTable(fromEntity, datasourceInfo)); sql.append(" "); sql.append((String) entry.getKey()); } } } else if ("theta-oracle".equals(datasourceInfo.joinStyle) || "theta-mssql".equals(datasourceInfo.joinStyle)) { // FROM clause Iterator meIter = modelViewEntity.getMemberModelMemberEntities().entrySet().iterator(); while (meIter.hasNext()) { Map.Entry entry = (Map.Entry) meIter.next(); ModelEntity fromEntity = modelViewEntity.getMemberModelEntity((String) entry.getKey()); sql.append(makeViewTable(fromEntity, datasourceInfo)); sql.append(" "); sql.append((String) entry.getKey()); if (meIter.hasNext()) sql.append(", "); } // JOIN clause(s): none needed, all the work done in the where clause for theta-oracle } else { throw new GenericModelException("The join-style " + datasourceInfo.joinStyle + " is not yet supported"); } } else { sql.append(modelEntity.getTableName(datasourceInfo)); } return sql.toString(); } /** Makes a WHERE clause String with "=?" if not null or " IS null" if null, all AND separated */ public static String makeWhereStringFromFields(List modelFields, Map fields, String operator) { return makeWhereStringFromFields(modelFields, fields, operator, null); } /** Makes a WHERE clause String with "=?" if not null or " IS null" if null, all AND separated */ public static String makeWhereStringFromFields(List modelFields, Map fields, String operator, List entityConditionParams) { if (modelFields.size() < 1) { return ""; } StringBuffer returnString = new StringBuffer(""); Iterator iter = modelFields.iterator(); while (iter.hasNext()) { Object item = iter.next(); Object name = null; ModelField modelField = null; if (item instanceof ModelField) { modelField = (ModelField) item; returnString.append(modelField.getColName()); name = modelField.getName(); } else { returnString.append(item); name = item; } Object fieldValue = fields.get(name); if (fieldValue != null && fieldValue != GenericEntity.NULL_FIELD) { returnString.append('='); addValue(returnString, modelField, fieldValue, entityConditionParams); } else { returnString.append(" IS NULL"); } if (iter.hasNext()) { returnString.append(' '); returnString.append(operator); returnString.append(' '); } } return returnString.toString(); } public static String makeWhereClause(ModelEntity modelEntity, List modelFields, Map fields, String operator, String joinStyle) throws GenericEntityException { StringBuffer whereString = new StringBuffer(""); if (modelFields != null && modelFields.size() > 0) { whereString.append(makeWhereStringFromFields(modelFields, fields, "AND")); } String viewClause = makeViewWhereClause(modelEntity, joinStyle); if (viewClause.length() > 0) { if (whereString.length() > 0) { whereString.append(' '); whereString.append(operator); whereString.append(' '); } whereString.append(viewClause); } if (whereString.length() > 0) { return " WHERE " + whereString.toString(); } return ""; } public static String makeViewWhereClause(ModelEntity modelEntity, String joinStyle) throws GenericEntityException { if (modelEntity instanceof ModelViewEntity) { StringBuffer whereString = new StringBuffer(); ModelViewEntity modelViewEntity = (ModelViewEntity) modelEntity; if ("ansi".equals(joinStyle) || "ansi-no-parenthesis".equals(joinStyle)) { // nothing to do here, all done in the JOIN clauses } else if ("theta-oracle".equals(joinStyle) || "theta-mssql".equals(joinStyle)) { boolean isOracleStyle = "theta-oracle".equals(joinStyle); boolean isMssqlStyle = "theta-mssql".equals(joinStyle); for (int i = 0; i < modelViewEntity.getViewLinksSize(); i++) { ModelViewEntity.ModelViewLink viewLink = modelViewEntity.getViewLink(i); ModelEntity linkEntity = modelViewEntity.getMemberModelEntity(viewLink.getEntityAlias()); ModelEntity relLinkEntity = modelViewEntity.getMemberModelEntity(viewLink.getRelEntityAlias()); if (linkEntity == null) { throw new GenericEntityException("Link entity not found with alias: " + viewLink.getEntityAlias() + " for entity: " + modelViewEntity.getEntityName()); } if (relLinkEntity == null) { throw new GenericEntityException("Rel-Link entity not found with alias: " + viewLink.getRelEntityAlias() + " for entity: " + modelViewEntity.getEntityName()); } // ModelViewEntity.ModelMemberEntity linkMemberEntity = modelViewEntity.getMemberModelMemberEntity(viewLink.getEntityAlias()); // ModelViewEntity.ModelMemberEntity relLinkMemberEntity = modelViewEntity.getMemberModelMemberEntity(viewLink.getRelEntityAlias()); for (int j = 0; j < viewLink.getKeyMapsSize(); j++) { ModelKeyMap keyMap = viewLink.getKeyMap(j); ModelField linkField = linkEntity.getField(keyMap.getFieldName()); ModelField relLinkField = relLinkEntity.getField(keyMap.getRelFieldName()); if (whereString.length() > 0) { whereString.append(" AND "); } whereString.append(viewLink.getEntityAlias()); whereString.append("."); whereString.append(filterColName(linkField.getColName())); // check to see whether the left or right members are optional, if so: // oracle: use the (+) on the optional side // mssql: use the * on the required side // NOTE: not testing if original table is optional, ONLY if related table is optional; otherwise things get really ugly... // if (isOracleStyle && linkMemberEntity.getOptional()) whereString.append(" (+) "); if (isMssqlStyle && viewLink.isRelOptional()) whereString.append("*"); whereString.append("="); // if (isMssqlStyle && linkMemberEntity.getOptional()) whereString.append("*"); if (isOracleStyle && viewLink.isRelOptional()) whereString.append(" (+) "); whereString.append(viewLink.getRelEntityAlias()); whereString.append("."); whereString.append(filterColName(relLinkField.getColName())); } } } else { throw new GenericModelException("The join-style " + joinStyle + " is not supported"); } if (whereString.length() > 0) { return "(" + whereString.toString() + ")"; } } return ""; } public static String makeOrderByClause(ModelEntity modelEntity, List orderBy, DatasourceInfo datasourceInfo) throws GenericModelException { return makeOrderByClause(modelEntity, orderBy, false, datasourceInfo); } public static String makeOrderByClause(ModelEntity modelEntity, List orderBy, boolean includeTablenamePrefix, DatasourceInfo datasourceInfo) throws GenericModelException { StringBuffer sql = new StringBuffer(""); //String fieldPrefix = includeTablenamePrefix ? (modelEntity.getTableName(datasourceInfo) + ".") : ""; if (orderBy != null && orderBy.size() > 0) { if (Debug.verboseOn()) Debug.logVerbose("Order by list contains: " + orderBy.size() + " entries.", module); OrderByList orderByList = new OrderByList(orderBy); orderByList.checkOrderBy(modelEntity); orderByList.makeOrderByString(sql, modelEntity, includeTablenamePrefix, datasourceInfo); } if (Debug.verboseOn()) Debug.logVerbose("makeOrderByClause: " + sql.toString(), module); return sql.toString(); } public static String makeViewTable(ModelEntity modelEntity, DatasourceInfo datasourceInfo) throws GenericEntityException { if (modelEntity instanceof ModelViewEntity) { StringBuffer sql = new StringBuffer("(SELECT "); Iterator fieldsIter = modelEntity.getFieldsIterator(); if (fieldsIter.hasNext()) { ModelField curField = (ModelField) fieldsIter.next(); String colname = curField.getColName(); sql.append(colname); sql.append(" AS "); sql.append(filterColName(colname)); while (fieldsIter.hasNext()) { curField = (ModelField) fieldsIter.next(); colname = curField.getColName(); sql.append(", "); sql.append(colname); sql.append(" AS "); sql.append(filterColName(colname)); } } sql.append(makeFromClause(modelEntity, datasourceInfo)); String viewWhereClause = makeViewWhereClause(modelEntity, datasourceInfo.joinStyle); if (UtilValidate.isNotEmpty(viewWhereClause)) { sql.append(" WHERE "); sql.append(viewWhereClause); } ModelViewEntity modelViewEntity = (ModelViewEntity)modelEntity; String groupByString = modelViewEntity.colNameString(modelViewEntity.getGroupBysCopy(), ", ", "", false); if (UtilValidate.isNotEmpty(groupByString)) { sql.append(" GROUP BY "); sql.append(groupByString); } sql.append(")"); return sql.toString(); } else { return modelEntity.getTableName(datasourceInfo); } } public static String filterColName(String colName) { return colName.replace('.', '_').replace('(','_').replace(')','_'); } /* ====================================================================== */ /* ====================================================================== */ /** * The elements (ModelFields) of the list are bound to an SQL statement * (SQL-Processor) * * @param sqlP * @param list * @param entity * @throws GenericEntityException */ public static void setValues(SQLProcessor sqlP, List list, GenericEntity entity, ModelFieldTypeReader modelFieldTypeReader) throws GenericEntityException { Iterator fieldIter = list.iterator(); while (fieldIter.hasNext()) { ModelField curField = (ModelField) fieldIter.next(); setValue(sqlP, curField, entity, modelFieldTypeReader); } } /** * The elements (ModelFields) of the list are bound to an SQL statement * (SQL-Processor), but values must not be null. * * @param sqlP * @param list * @param dummyValue * @param modelFieldTypeReader * @throws GenericEntityException */ public static void setValuesWhereClause(SQLProcessor sqlP, List list, GenericValue dummyValue, ModelFieldTypeReader modelFieldTypeReader) throws GenericEntityException { Iterator fieldIter = list.iterator(); while (fieldIter.hasNext()) { ModelField curField = (ModelField) fieldIter.next(); // for where clause variables only setValue if not null... if (dummyValue.get(curField.getName()) != null) { setValue(sqlP, curField, dummyValue, modelFieldTypeReader); } } } /** * Get all primary keys from the model entity and bind their values * to the an SQL statement (SQL-Processor) * * @param sqlP * @param modelEntity * @param entity * @param modelFieldTypeReader * @throws GenericEntityException */ public static void setPkValues(SQLProcessor sqlP, ModelEntity modelEntity, GenericEntity entity, ModelFieldTypeReader modelFieldTypeReader) throws GenericEntityException { Iterator pksIter = modelEntity.getPksIterator(); while (pksIter.hasNext()) { ModelField curField = (ModelField) pksIter.next(); // for where clause variables only setValue if not null... if (entity.dangerousGetNoCheckButFast(curField) != null) { setValue(sqlP, curField, entity, modelFieldTypeReader); } } } public static void getValue(ResultSet rs, int ind, ModelField curField, GenericEntity entity, ModelFieldTypeReader modelFieldTypeReader) throws GenericEntityException { ModelFieldType mft = modelFieldTypeReader.getModelFieldType(curField.getType()); if (mft == null) { throw new GenericModelException("definition fieldType " + curField.getType() + " not found, cannot getValue for field " + entity.getEntityName() + "." + curField.getName() + "."); } String fieldType = mft.getJavaType(); try { // checking to see if the object is null is really only necessary for the numbers int typeValue = getType(fieldType); ResultSetMetaData rsmd = rs.getMetaData(); int colType = rsmd.getColumnType(ind); if (typeValue <= 4 || typeValue >= 11) { switch (typeValue) { case 1: if (java.sql.Types.CLOB == colType) { // Debug.logInfo("For field " + curField.getName() + " of entity " + entity.getEntityName() + " getString is a CLOB, trying getCharacterStream", module); // if the String is empty, try to get a text input stream, this is required for some databases for larger fields, like CLOBs Clob valueClob = rs.getClob(ind); Reader valueReader = null; if (valueClob != null) { valueReader = valueClob.getCharacterStream(); } //Reader valueReader = rs.getCharacterStream(ind); if (valueReader != null) { char[] inCharBuffer = new char[CHAR_BUFFER_SIZE]; StringBuffer strBuf = new StringBuffer(); int charsRead = 0; try { while ((charsRead = valueReader.read(inCharBuffer, 0, CHAR_BUFFER_SIZE)) > 0) { strBuf.append(inCharBuffer, 0, charsRead); } valueReader.close(); } catch (IOException e) { throw new GenericEntityException("Error reading long character stream for field " + curField.getName() + " of entity " + entity.getEntityName(), e); } entity.dangerousSetNoCheckButFast(curField, strBuf.toString()); } else { entity.dangerousSetNoCheckButFast(curField, null); } } else { String value = rs.getString(ind); entity.dangerousSetNoCheckButFast(curField, value); } break; case 2: entity.dangerousSetNoCheckButFast(curField, rs.getTimestamp(ind)); break; case 3: entity.dangerousSetNoCheckButFast(curField, rs.getTime(ind)); break; case 4: entity.dangerousSetNoCheckButFast(curField, rs.getDate(ind)); break; case 11: Object obj = null; InputStream binaryInput = null; byte[] fieldBytes = rs.getBytes(ind); if (fieldBytes != null && fieldBytes.length > 0) { binaryInput = new ByteArrayInputStream(fieldBytes); } if (fieldBytes != null && fieldBytes.length <= 0) { Debug.logWarning("Got bytes back for Object field with length: " + fieldBytes.length + " while getting value : " + curField.getName() + " [" + curField.getColName() + "] (" + ind + "): ", module); } //alt 1: binaryInput = rs.getBinaryStream(ind); //alt 2: Blob blobLocator = rs.getBlob(ind); //if (blobLocator != null) { // binaryInput = blobLocator.getBinaryStream(); //} if (binaryInput != null) { ObjectInputStream in = null; try { in = new ObjectInputStream(binaryInput); obj = in.readObject(); } catch (IOException ex) { throw new GenericDataSourceException("Unable to read BLOB data from input stream while getting value : " + curField.getName() + " [" + curField.getColName() + "] (" + ind + "): " + ex.toString(), ex); } catch (ClassNotFoundException ex) { throw new GenericDataSourceException("Class not found: Unable to cast BLOB data to an Java object while getting value : " + curField.getName() + " [" + curField.getColName() + "] (" + ind + "): " + ex.toString(), ex); } finally { if (in != null) { try { in.close(); } catch (IOException e) { throw new GenericDataSourceException("Unable to close binary input stream while getting value : " + curField.getName() + " [" + curField.getColName() + "] (" + ind + "): " + e.toString(), e); } } } } binaryInput = null; entity.dangerousSetNoCheckButFast(curField, obj); break; case 12: entity.dangerousSetNoCheckButFast(curField, rs.getBlob(ind)); break; case 13: entity.dangerousSetNoCheckButFast(curField, rs.getClob(ind)); break; case 14: case 15: entity.dangerousSetNoCheckButFast(curField, rs.getObject(ind)); break; } } else { switch (typeValue) { case 5: int intValue = rs.getInt(ind); if (rs.wasNull()) { entity.dangerousSetNoCheckButFast(curField, null); } else { entity.dangerousSetNoCheckButFast(curField, new Integer(intValue)); } break; case 6: long longValue = rs.getLong(ind); if (rs.wasNull()) { entity.dangerousSetNoCheckButFast(curField, null); } else { entity.dangerousSetNoCheckButFast(curField, new Long(longValue)); } break; case 7: float floatValue = rs.getFloat(ind); if (rs.wasNull()) { entity.dangerousSetNoCheckButFast(curField, null); } else { entity.dangerousSetNoCheckButFast(curField, new Float(floatValue)); } break; case 8: double doubleValue = rs.getDouble(ind); if (rs.wasNull()) { entity.dangerousSetNoCheckButFast(curField, null); } else { entity.dangerousSetNoCheckButFast(curField, new Double(doubleValue)); } break; case 9: BigDecimal bigDecimalValue = rs.getBigDecimal(ind); if (rs.wasNull()) { entity.dangerousSetNoCheckButFast(curField, null); } else { entity.dangerousSetNoCheckButFast(curField, bigDecimalValue); } break; case 10: boolean booleanValue = rs.getBoolean(ind); if (rs.wasNull()) { entity.dangerousSetNoCheckButFast(curField, null); } else { entity.dangerousSetNoCheckButFast(curField, new Boolean(booleanValue)); } break; } } } catch (SQLException sqle) { throw new GenericDataSourceException("SQL Exception while getting value : " + curField.getName() + " [" + curField.getColName() + "] (" + ind + ")", sqle); } } public static void setValue(SQLProcessor sqlP, ModelField modelField, GenericEntity entity, ModelFieldTypeReader modelFieldTypeReader) throws GenericEntityException { Object fieldValue = entity.dangerousGetNoCheckButFast(modelField); setValue(sqlP, modelField, entity.getEntityName(), fieldValue, modelFieldTypeReader); } public static void setValue(SQLProcessor sqlP, ModelField modelField, String entityName, Object fieldValue, ModelFieldTypeReader modelFieldTypeReader) throws GenericEntityException { ModelFieldType mft = modelFieldTypeReader.getModelFieldType(modelField.getType()); if (mft == null) { throw new GenericModelException("GenericDAO.getValue: definition fieldType " + modelField.getType() + " not found, cannot setValue for field " + entityName + "." + modelField.getName() + "."); } // if the value is the GenericEntity.NullField, treat as null if (fieldValue == GenericEntity.NULL_FIELD) { fieldValue = null; } String fieldType = mft.getJavaType(); if (fieldValue != null) { if (!ObjectType.instanceOf(fieldValue, fieldType)) { // this is only an info level message because under normal operation for most JDBC // drivers this will be okay, but if not then the JDBC driver will throw an exception // and when lower debug levels are on this should help give more info on what happened Class fieldClass = fieldValue.getClass(); String fieldClassName = fieldClass.getName(); if (Debug.verboseOn()) Debug.logVerbose("type of field " + entityName + "." + modelField.getName() + " is " + fieldClassName + ", was expecting " + mft.getJavaType() + "; this may " + "indicate an error in the configuration or in the class, and may result " + "in an SQL-Java data conversion error. Will use the real field type: " + fieldClassName + ", not the definition.", module); fieldType = fieldClassName; } } try { int typeValue = getType(fieldType); switch (typeValue) { case 1: sqlP.setValue((String) fieldValue); break; case 2: sqlP.setValue((java.sql.Timestamp) fieldValue); break; case 3: sqlP.setValue((java.sql.Time) fieldValue); break; case 4: sqlP.setValue((java.sql.Date) fieldValue); break; case 5: sqlP.setValue((java.lang.Integer) fieldValue); break; case 6: sqlP.setValue((java.lang.Long) fieldValue); break; case 7: sqlP.setValue((java.lang.Float) fieldValue); break; case 8: sqlP.setValue((java.lang.Double) fieldValue); break; case 9: sqlP.setValue((java.math.BigDecimal) fieldValue); break; case 10: sqlP.setValue((java.lang.Boolean) fieldValue); break; case 11: sqlP.setBinaryStream(fieldValue); break; case 12: sqlP.setValue((java.sql.Blob) fieldValue); break; case 13: sqlP.setValue((java.sql.Clob) fieldValue); break; case 14: if (fieldValue != null) { sqlP.setValue(new java.sql.Date(((java.util.Date) fieldValue).getTime())); } else { sqlP.setValue((java.sql.Date) null); } break; case 15: sqlP.setValue((java.util.Collection) fieldValue); break; } } catch (GenericNotImplementedException e) { throw new GenericNotImplementedException("Not Implemented Exception while setting value on field [" + modelField.getName() + "] of entity " + entityName + ": " + e.toString(), e); } catch (SQLException sqle) { throw new GenericDataSourceException("SQL Exception while setting value on field [" + modelField.getName() + "] of entity " + entityName + ": ", sqle); } } protected static Map fieldTypeMap = FastMap.newInstance(); static { fieldTypeMap.put("java.lang.String", new Integer(1)); fieldTypeMap.put("String", new Integer(1)); fieldTypeMap.put("java.sql.Timestamp", new Integer(2)); fieldTypeMap.put("Timestamp", new Integer(2)); fieldTypeMap.put("java.sql.Time", new Integer(3)); fieldTypeMap.put("Time", new Integer(3)); fieldTypeMap.put("java.sql.Date", new Integer(4)); fieldTypeMap.put("Date", new Integer(4)); fieldTypeMap.put("java.lang.Integer", new Integer(5)); fieldTypeMap.put("Integer", new Integer(5)); fieldTypeMap.put("java.lang.Long", new Integer(6)); fieldTypeMap.put("Long", new Integer(6)); fieldTypeMap.put("java.lang.Float", new Integer(7)); fieldTypeMap.put("Float", new Integer(7)); fieldTypeMap.put("java.lang.Double", new Integer(8)); fieldTypeMap.put("Double", new Integer(8)); fieldTypeMap.put("java.math.BigDecimal", new Integer(9)); fieldTypeMap.put("BigDecimal", new Integer(9)); fieldTypeMap.put("java.lang.Boolean", new Integer(10)); fieldTypeMap.put("Boolean", new Integer(10)); fieldTypeMap.put("java.lang.Object", new Integer(11)); fieldTypeMap.put("Object", new Integer(11)); fieldTypeMap.put("java.sql.Blob", new Integer(12)); fieldTypeMap.put("Blob", new Integer(12)); fieldTypeMap.put("java.sql.Clob", new Integer(13)); fieldTypeMap.put("Clob", new Integer(13)); fieldTypeMap.put("java.util.Date", new Integer(14)); // all of these treated as Collection fieldTypeMap.put("java.util.ArrayList", new Integer(15)); fieldTypeMap.put("java.util.HashSet", new Integer(15)); fieldTypeMap.put("java.util.LinkedHashSet", new Integer(15)); fieldTypeMap.put("java.util.LinkedList", new Integer(15)); } public static int getType(String fieldType) throws GenericNotImplementedException { Integer val = (Integer) fieldTypeMap.get(fieldType); if (val == null) { throw new GenericNotImplementedException("Java type " + fieldType + " not currently supported. Sorry."); } return val.intValue(); } public static void addValueSingle(StringBuffer buffer, ModelField field, Object value, List params) { if (field != null) { buffer.append('?'); } else { buffer.append('\'').append(value).append('\''); } if (field != null && params != null) params.add(new EntityConditionParam(field, value)); } public static void addValue(StringBuffer buffer, ModelField field, Object value, List params) { if (value instanceof Collection) { buffer.append("( "); Iterator it = ((Collection) value).iterator(); while (it.hasNext()) { Object thisValue = it.next(); addValueSingle(buffer, field, thisValue, params); if (it.hasNext()) buffer.append(", "); } buffer.append(" )"); } else { addValueSingle(buffer, field, value, params); } } }