0001: /*
0002: * $Id: SqlJdbcUtil.java,v 1.17 2004/02/16 17:37:58 ajzeneski Exp $
0003: *
0004: * Copyright (c) 2001, 2002 The Open For Business Project - www.ofbiz.org
0005: *
0006: * Permission is hereby granted, free of charge, to any person obtaining a
0007: * copy of this software and associated documentation files (the "Software"),
0008: * to deal in the Software without restriction, including without limitation
0009: * the rights to use, copy, modify, merge, publish, distribute, sublicense,
0010: * and/or sell copies of the Software, and to permit persons to whom the
0011: * Software is furnished to do so, subject to the following conditions:
0012: *
0013: * The above copyright notice and this permission notice shall be included
0014: * in all copies or substantial portions of the Software.
0015: *
0016: * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
0017: * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
0018: * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
0019: * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
0020: * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT
0021: * OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
0022: * THE USE OR OTHER DEALINGS IN THE SOFTWARE.
0023: */
0024: package org.ofbiz.entity.jdbc;
0025:
0026: import java.io.ByteArrayInputStream;
0027: import java.io.IOException;
0028: import java.io.InputStream;
0029: import java.io.ObjectInputStream;
0030: import java.io.Reader;
0031: import java.sql.ResultSet;
0032: import java.sql.ResultSetMetaData;
0033: import java.sql.SQLException;
0034: import java.util.HashMap;
0035: import java.util.Iterator;
0036: import java.util.LinkedList;
0037: import java.util.List;
0038: import java.util.Map;
0039: import java.util.Set;
0040: import java.util.TreeSet;
0041:
0042: import org.ofbiz.base.util.Debug;
0043: import org.ofbiz.base.util.ObjectType;
0044: import org.ofbiz.base.util.UtilValidate;
0045: import org.ofbiz.entity.GenericDataSourceException;
0046: import org.ofbiz.entity.GenericEntity;
0047: import org.ofbiz.entity.GenericEntityException;
0048: import org.ofbiz.entity.GenericModelException;
0049: import org.ofbiz.entity.GenericNotImplementedException;
0050: import org.ofbiz.entity.GenericValue;
0051: import org.ofbiz.entity.condition.EntityConditionParam;
0052: import org.ofbiz.entity.config.EntityConfigUtil;
0053: import org.ofbiz.entity.datasource.GenericDAO;
0054: import org.ofbiz.entity.model.ModelEntity;
0055: import org.ofbiz.entity.model.ModelField;
0056: import org.ofbiz.entity.model.ModelFieldType;
0057: import org.ofbiz.entity.model.ModelFieldTypeReader;
0058: import org.ofbiz.entity.model.ModelKeyMap;
0059: import org.ofbiz.entity.model.ModelViewEntity;
0060:
0061: /**
0062: * GenericDAO Utility methods for general tasks
0063: *
0064: * @author <a href="mailto:jonesde@ofbiz.org">David E. Jones</a>
0065: * @author <a href="mailto:chris_maurer@altavista.com">Chris Maurer</a>
0066: * @author <a href="mailto:jaz@ofbiz.org">Andy Zeneski</a>
0067: * @author <a href="mailto:jdonnerstag@eds.de">Juergen Donnerstag</a>
0068: * @author <a href="mailto:peterm@miraculum.com">Peter Moon</a>
0069: * @version $Revision: 1.17 $
0070: * @since 2.0
0071: */
0072: public class SqlJdbcUtil {
0073: public static final String module = GenericDAO.class.getName();
0074:
0075: public static final int CHAR_BUFFER_SIZE = 4096;
0076:
0077: /** Makes the FROM clause and when necessary the JOIN clause(s) as well */
0078: public static String makeFromClause(ModelEntity modelEntity,
0079: EntityConfigUtil.DatasourceInfo datasourceInfo)
0080: throws GenericEntityException {
0081: StringBuffer sql = new StringBuffer(" FROM ");
0082:
0083: if (modelEntity instanceof ModelViewEntity) {
0084: ModelViewEntity modelViewEntity = (ModelViewEntity) modelEntity;
0085:
0086: if ("ansi".equals(datasourceInfo.joinStyle)
0087: || "ansi-no-parenthesis"
0088: .equals(datasourceInfo.joinStyle)) {
0089: boolean useParenthesis = true;
0090: if ("ansi-no-parenthesis"
0091: .equals(datasourceInfo.joinStyle)) {
0092: useParenthesis = false;
0093: }
0094:
0095: // FROM clause: in this case will be a bunch of joins that correspond with the view-links
0096:
0097: // BIG NOTE on the JOIN clauses: the order of joins is determined by the order of the
0098: // view-links; for more flexible order we'll have to figure something else out and
0099: // extend the DTD for the nested view-link elements or something
0100:
0101: // At this point it is assumed that in each view-link the left hand alias will
0102: // either be the first alias in the series or will already be in a previous
0103: // view-link and already be in the big join; SO keep a set of all aliases
0104: // in the join so far and if the left entity alias isn't there yet, and this
0105: // isn't the first one, throw an exception
0106: Set joinedAliasSet = new TreeSet();
0107:
0108: // TODO: at view-link read time make sure they are ordered properly so that each
0109: // left hand alias after the first view-link has already been linked before
0110:
0111: StringBuffer openParens = null;
0112: if (useParenthesis)
0113: openParens = new StringBuffer();
0114: StringBuffer restOfStatement = new StringBuffer();
0115:
0116: for (int i = 0; i < modelViewEntity.getViewLinksSize(); i++) {
0117: // don't put starting parenthesis
0118: if (i > 0 && useParenthesis)
0119: openParens.append('(');
0120:
0121: ModelViewEntity.ModelViewLink viewLink = modelViewEntity
0122: .getViewLink(i);
0123:
0124: ModelEntity linkEntity = modelViewEntity
0125: .getMemberModelEntity(viewLink
0126: .getEntityAlias());
0127: ModelEntity relLinkEntity = modelViewEntity
0128: .getMemberModelEntity(viewLink
0129: .getRelEntityAlias());
0130:
0131: // ModelViewEntity.ModelMemberEntity linkMemberEntity = modelViewEntity.getMemberModelMemberEntity(viewLink.getEntityAlias());
0132: // ModelViewEntity.ModelMemberEntity relLinkMemberEntity = modelViewEntity.getMemberModelMemberEntity(viewLink.getRelEntityAlias());
0133:
0134: if (i == 0) {
0135: // this is the first referenced member alias, so keep track of it for future use...
0136: restOfStatement.append(makeViewTable(
0137: linkEntity, datasourceInfo));
0138: //another possible one that some dbs might need, but not sure of any yet: restOfStatement.append(" AS ");
0139: restOfStatement.append(" ");
0140: restOfStatement.append(viewLink
0141: .getEntityAlias());
0142:
0143: joinedAliasSet.add(viewLink.getEntityAlias());
0144: } else {
0145: // make sure the left entity alias is already in the join...
0146: if (!joinedAliasSet.contains(viewLink
0147: .getEntityAlias())) {
0148: throw new GenericModelException(
0149: "Tried to link the "
0150: + viewLink.getEntityAlias()
0151: + " alias to the "
0152: + viewLink
0153: .getRelEntityAlias()
0154: + " alias of the "
0155: + modelViewEntity
0156: .getEntityName()
0157: + " 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.");
0158: }
0159: }
0160: // now put the rel (right) entity alias into the set that is in the join
0161: joinedAliasSet.add(viewLink.getRelEntityAlias());
0162:
0163: if (viewLink.isRelOptional()) {
0164: restOfStatement.append(" LEFT OUTER JOIN ");
0165: } else {
0166: restOfStatement.append(" INNER JOIN ");
0167: }
0168:
0169: restOfStatement.append(makeViewTable(relLinkEntity,
0170: datasourceInfo));
0171: //another possible one that some dbs might need, but not sure of any yet: restOfStatement.append(" AS ");
0172: restOfStatement.append(" ");
0173: restOfStatement
0174: .append(viewLink.getRelEntityAlias());
0175: restOfStatement.append(" ON ");
0176:
0177: StringBuffer condBuffer = new StringBuffer();
0178:
0179: for (int j = 0; j < viewLink.getKeyMapsSize(); j++) {
0180: ModelKeyMap keyMap = viewLink.getKeyMap(j);
0181: ModelField linkField = linkEntity
0182: .getField(keyMap.getFieldName());
0183: ModelField relLinkField = relLinkEntity
0184: .getField(keyMap.getRelFieldName());
0185:
0186: if (condBuffer.length() > 0) {
0187: condBuffer.append(" AND ");
0188: }
0189: condBuffer.append(viewLink.getEntityAlias());
0190: condBuffer.append(".");
0191: condBuffer.append(filterColName(linkField
0192: .getColName()));
0193:
0194: condBuffer.append(" = ");
0195:
0196: condBuffer.append(viewLink.getRelEntityAlias());
0197: condBuffer.append(".");
0198: condBuffer.append(filterColName(relLinkField
0199: .getColName()));
0200: }
0201: if (condBuffer.length() == 0) {
0202: throw new GenericModelException(
0203: "No view-link/join key-maps found for the "
0204: + viewLink.getEntityAlias()
0205: + " and the "
0206: + viewLink.getRelEntityAlias()
0207: + " member-entities of the "
0208: + modelViewEntity
0209: .getEntityName()
0210: + " view-entity.");
0211: }
0212: restOfStatement.append(condBuffer.toString());
0213:
0214: // don't put ending parenthesis
0215: if (i < (modelViewEntity.getViewLinksSize() - 1)
0216: && useParenthesis)
0217: restOfStatement.append(')');
0218: }
0219:
0220: if (useParenthesis)
0221: sql.append(openParens.toString());
0222: sql.append(restOfStatement.toString());
0223:
0224: // handle tables not included in view-link
0225: Iterator meIter = modelViewEntity
0226: .getMemberModelMemberEntities().entrySet()
0227: .iterator();
0228: boolean fromEmpty = restOfStatement.length() == 0;
0229:
0230: while (meIter.hasNext()) {
0231: Map.Entry entry = (Map.Entry) meIter.next();
0232: ModelEntity fromEntity = modelViewEntity
0233: .getMemberModelEntity((String) entry
0234: .getKey());
0235:
0236: if (!joinedAliasSet.contains((String) entry
0237: .getKey())) {
0238: if (!fromEmpty)
0239: sql.append(", ");
0240: fromEmpty = false;
0241:
0242: sql.append(makeViewTable(fromEntity,
0243: datasourceInfo));
0244: sql.append(" ");
0245: sql.append((String) entry.getKey());
0246: }
0247: }
0248:
0249: } else if ("theta-oracle".equals(datasourceInfo.joinStyle)
0250: || "theta-mssql".equals(datasourceInfo.joinStyle)) {
0251: // FROM clause
0252: Iterator meIter = modelViewEntity
0253: .getMemberModelMemberEntities().entrySet()
0254: .iterator();
0255:
0256: while (meIter.hasNext()) {
0257: Map.Entry entry = (Map.Entry) meIter.next();
0258: ModelEntity fromEntity = modelViewEntity
0259: .getMemberModelEntity((String) entry
0260: .getKey());
0261:
0262: sql
0263: .append(makeViewTable(fromEntity,
0264: datasourceInfo));
0265: sql.append(" ");
0266: sql.append((String) entry.getKey());
0267: if (meIter.hasNext())
0268: sql.append(", ");
0269: }
0270:
0271: // JOIN clause(s): none needed, all the work done in the where clause for theta-oracle
0272: } else {
0273: throw new GenericModelException("The join-style "
0274: + datasourceInfo.joinStyle
0275: + " is not yet supported");
0276: }
0277: } else {
0278: sql.append(modelEntity.getTableName(datasourceInfo));
0279: }
0280: return sql.toString();
0281: }
0282:
0283: /** Makes a WHERE clause String with "<col name>=?" if not null or "<col name> IS null" if null, all AND separated */
0284: public static String makeWhereStringFromFields(List modelFields,
0285: Map fields, String operator) {
0286: return makeWhereStringFromFields(modelFields, fields, operator,
0287: null);
0288: }
0289:
0290: /** Makes a WHERE clause String with "<col name>=?" if not null or "<col name> IS null" if null, all AND separated */
0291: public static String makeWhereStringFromFields(List modelFields,
0292: Map fields, String operator, List entityConditionParams) {
0293: StringBuffer returnString = new StringBuffer("");
0294:
0295: if (modelFields.size() < 1) {
0296: return "";
0297: }
0298: Iterator iter = modelFields.iterator();
0299:
0300: while (iter.hasNext()) {
0301: Object item = iter.next();
0302: Object name = null;
0303: ModelField modelField = null;
0304: if (item instanceof ModelField) {
0305: modelField = (ModelField) item;
0306: returnString.append(modelField.getColName());
0307: name = modelField.getName();
0308: } else {
0309: returnString.append(item);
0310: name = item;
0311: }
0312: Object fieldValue = fields.get(name);
0313:
0314: if (fieldValue != null) {
0315: returnString.append('=');
0316: addValue(returnString, modelField, fieldValue,
0317: entityConditionParams);
0318: } else {
0319: returnString.append(" IS NULL");
0320: }
0321:
0322: if (iter.hasNext()) {
0323: returnString.append(' ');
0324: returnString.append(operator);
0325: returnString.append(' ');
0326: }
0327: }
0328:
0329: return returnString.toString();
0330: }
0331:
0332: public static String makeWhereClause(ModelEntity modelEntity,
0333: List modelFields, Map fields, String operator,
0334: String joinStyle) throws GenericEntityException {
0335: StringBuffer whereString = new StringBuffer("");
0336:
0337: if (modelFields != null && modelFields.size() > 0) {
0338: whereString.append(makeWhereStringFromFields(modelFields,
0339: fields, "AND"));
0340: }
0341:
0342: String viewClause = makeViewWhereClause(modelEntity, joinStyle);
0343:
0344: if (viewClause.length() > 0) {
0345: if (whereString.length() > 0) {
0346: whereString.append(' ');
0347: whereString.append(operator);
0348: whereString.append(' ');
0349: }
0350:
0351: whereString.append(viewClause);
0352: }
0353:
0354: if (whereString.length() > 0) {
0355: return " WHERE " + whereString.toString();
0356: }
0357:
0358: return "";
0359: }
0360:
0361: public static String makeViewWhereClause(ModelEntity modelEntity,
0362: String joinStyle) throws GenericEntityException {
0363: if (modelEntity instanceof ModelViewEntity) {
0364: StringBuffer whereString = new StringBuffer();
0365: ModelViewEntity modelViewEntity = (ModelViewEntity) modelEntity;
0366:
0367: if ("ansi".equals(joinStyle)
0368: || "ansi-no-parenthesis".equals(joinStyle)) {
0369: // nothing to do here, all done in the JOIN clauses
0370: } else if ("theta-oracle".equals(joinStyle)
0371: || "theta-mssql".equals(joinStyle)) {
0372: boolean isOracleStyle = "theta-oracle"
0373: .equals(joinStyle);
0374: boolean isMssqlStyle = "theta-mssql".equals(joinStyle);
0375:
0376: for (int i = 0; i < modelViewEntity.getViewLinksSize(); i++) {
0377: ModelViewEntity.ModelViewLink viewLink = modelViewEntity
0378: .getViewLink(i);
0379:
0380: ModelEntity linkEntity = modelViewEntity
0381: .getMemberModelEntity(viewLink
0382: .getEntityAlias());
0383: ModelEntity relLinkEntity = modelViewEntity
0384: .getMemberModelEntity(viewLink
0385: .getRelEntityAlias());
0386:
0387: if (linkEntity == null) {
0388: throw new GenericEntityException(
0389: "Link entity not found with alias: "
0390: + viewLink.getEntityAlias()
0391: + " for entity: "
0392: + modelViewEntity
0393: .getEntityName());
0394: }
0395:
0396: if (relLinkEntity == null) {
0397: throw new GenericEntityException(
0398: "Rel-Link entity not found with alias: "
0399: + viewLink.getRelEntityAlias()
0400: + " for entity: "
0401: + modelViewEntity
0402: .getEntityName());
0403: }
0404:
0405: // ModelViewEntity.ModelMemberEntity linkMemberEntity = modelViewEntity.getMemberModelMemberEntity(viewLink.getEntityAlias());
0406: // ModelViewEntity.ModelMemberEntity relLinkMemberEntity = modelViewEntity.getMemberModelMemberEntity(viewLink.getRelEntityAlias());
0407:
0408: for (int j = 0; j < viewLink.getKeyMapsSize(); j++) {
0409: ModelKeyMap keyMap = viewLink.getKeyMap(j);
0410: ModelField linkField = linkEntity
0411: .getField(keyMap.getFieldName());
0412: ModelField relLinkField = relLinkEntity
0413: .getField(keyMap.getRelFieldName());
0414:
0415: if (whereString.length() > 0) {
0416: whereString.append(" AND ");
0417: }
0418: whereString.append(viewLink.getEntityAlias());
0419: whereString.append(".");
0420: whereString.append(filterColName(linkField
0421: .getColName()));
0422:
0423: // check to see whether the left or right members are optional, if so:
0424: // oracle: use the (+) on the optional side
0425: // mssql: use the * on the required side
0426:
0427: // NOTE: not testing if original table is optional, ONLY if related table is optional; otherwise things get really ugly...
0428: // if (isOracleStyle && linkMemberEntity.getOptional()) whereString.append(" (+) ");
0429: if (isMssqlStyle && viewLink.isRelOptional())
0430: whereString.append("*");
0431: whereString.append("=");
0432: // if (isMssqlStyle && linkMemberEntity.getOptional()) whereString.append("*");
0433: if (isOracleStyle && viewLink.isRelOptional())
0434: whereString.append(" (+) ");
0435:
0436: whereString
0437: .append(viewLink.getRelEntityAlias());
0438: whereString.append(".");
0439: whereString.append(filterColName(relLinkField
0440: .getColName()));
0441: }
0442: }
0443: } else {
0444: throw new GenericModelException("The join-style "
0445: + joinStyle + " is not yet supported");
0446: }
0447:
0448: if (whereString.length() > 0) {
0449: return "(" + whereString.toString() + ")";
0450: }
0451: }
0452: return "";
0453: }
0454:
0455: public static String makeOrderByClause(ModelEntity modelEntity,
0456: List orderBy, EntityConfigUtil.DatasourceInfo datasourceInfo) {
0457: return makeOrderByClause(modelEntity, orderBy, false,
0458: datasourceInfo);
0459: }
0460:
0461: public static String makeOrderByClause(ModelEntity modelEntity,
0462: List orderBy, boolean includeTablenamePrefix,
0463: EntityConfigUtil.DatasourceInfo datasourceInfo) {
0464: StringBuffer sql = new StringBuffer("");
0465: String fieldPrefix = includeTablenamePrefix ? (modelEntity
0466: .getTableName(datasourceInfo) + ".") : "";
0467:
0468: if (orderBy != null && orderBy.size() > 0) {
0469: if (Debug.verboseOn())
0470: Debug.logVerbose("Order by list contains: "
0471: + orderBy.size() + " entries.", module);
0472: List orderByStrings = new LinkedList();
0473:
0474: for (int oi = 0; oi < orderBy.size(); oi++) {
0475: String keyName = (String) orderBy.get(oi);
0476: String ext = null;
0477:
0478: // check for ASC/DESC
0479: int spaceIdx = keyName.indexOf(" ");
0480:
0481: if (spaceIdx > 0) {
0482: ext = keyName.substring(spaceIdx);
0483: keyName = keyName.substring(0, spaceIdx);
0484: }
0485: // optional way -/+
0486: if (keyName.startsWith("-") || keyName.startsWith("+")) {
0487: ext = keyName.startsWith("-") ? " DESC" : " ASC";
0488: keyName = keyName.substring(1);
0489: }
0490:
0491: for (int fi = 0; fi < modelEntity.getFieldsSize(); fi++) {
0492: ModelField curField = modelEntity.getField(fi);
0493: String fieldName = curField.getName();
0494:
0495: if (fieldName.equals(keyName)) {
0496: if (ext != null) {
0497: orderByStrings
0498: .add(fieldPrefix
0499: + modelEntity
0500: .getColNameOrAlias(fieldName)
0501: + ext);
0502: } else {
0503: orderByStrings
0504: .add(fieldPrefix
0505: + modelEntity
0506: .getColNameOrAlias(fieldName));
0507: }
0508: }
0509: }
0510: }
0511:
0512: if (orderByStrings.size() > 0) {
0513: sql.append(" ORDER BY ");
0514:
0515: Iterator iter = orderByStrings.iterator();
0516:
0517: while (iter.hasNext()) {
0518: String curString = (String) iter.next();
0519:
0520: sql.append(curString);
0521: if (iter.hasNext())
0522: sql.append(", ");
0523: }
0524: }
0525: }
0526: if (Debug.verboseOn())
0527: Debug.logVerbose("makeOrderByClause: " + sql.toString(),
0528: module);
0529: return sql.toString();
0530: }
0531:
0532: public static String makeViewTable(ModelEntity modelEntity,
0533: EntityConfigUtil.DatasourceInfo datasourceInfo)
0534: throws GenericEntityException {
0535: if (modelEntity instanceof ModelViewEntity) {
0536: StringBuffer sql = new StringBuffer("(SELECT ");
0537: List fields = modelEntity.getFieldsCopy();
0538: if (fields.size() > 0) {
0539: String colname = ((ModelField) fields.get(0))
0540: .getColName();
0541: sql.append(colname);
0542: sql.append(" AS ");
0543: sql.append(filterColName(colname));
0544: for (int i = 1; i < fields.size(); i++) {
0545: colname = ((ModelField) fields.get(i)).getColName();
0546: sql.append(", ");
0547: sql.append(colname);
0548: sql.append(" AS ");
0549: sql.append(filterColName(colname));
0550: }
0551: }
0552: sql.append(makeFromClause(modelEntity, datasourceInfo));
0553: String viewWhereClause = makeViewWhereClause(modelEntity,
0554: datasourceInfo.joinStyle);
0555: if (viewWhereClause != null && viewWhereClause.length() > 0) {
0556: sql.append(" WHERE ");
0557: sql.append(viewWhereClause);
0558: }
0559: ModelViewEntity modelViewEntity = (ModelViewEntity) modelEntity;
0560: String groupByString = modelViewEntity.colNameString(
0561: modelViewEntity.getGroupBysCopy(), ", ", "", false);
0562: if (UtilValidate.isNotEmpty(groupByString)) {
0563: sql.append(" GROUP BY ");
0564: sql.append(groupByString);
0565: }
0566:
0567: sql.append(")");
0568: return sql.toString();
0569: } else {
0570: return modelEntity.getTableName(datasourceInfo);
0571: }
0572: }
0573:
0574: public static String filterColName(String colName) {
0575: return colName.replace('.', '_').replace('(', '_').replace(')',
0576: '_');
0577: }
0578:
0579: /* ====================================================================== */
0580:
0581: /* ====================================================================== */
0582:
0583: /**
0584: * The elements (ModelFields) of the list are bound to an SQL statement
0585: * (SQL-Processor)
0586: *
0587: * @param sqlP
0588: * @param list
0589: * @param entity
0590: * @throws GenericEntityException
0591: */
0592: public static void setValues(SQLProcessor sqlP, List list,
0593: GenericEntity entity,
0594: ModelFieldTypeReader modelFieldTypeReader)
0595: throws GenericEntityException {
0596: for (int i = 0; i < list.size(); i++) {
0597: ModelField curField = (ModelField) list.get(i);
0598: setValue(sqlP, curField, entity, modelFieldTypeReader);
0599: }
0600: }
0601:
0602: /**
0603: * The elements (ModelFields) of the list are bound to an SQL statement
0604: * (SQL-Processor), but values must not be null.
0605: *
0606: * @param sqlP
0607: * @param list
0608: * @param dummyValue
0609: * @param modelFieldTypeReader
0610: * @throws GenericEntityException
0611: */
0612: public static void setValuesWhereClause(SQLProcessor sqlP,
0613: List list, GenericValue dummyValue,
0614: ModelFieldTypeReader modelFieldTypeReader)
0615: throws GenericEntityException {
0616:
0617: for (int i = 0; i < list.size(); i++) {
0618: ModelField curField = (ModelField) list.get(i);
0619:
0620: // for where clause variables only setValue if not null...
0621: if (dummyValue.get(curField.getName()) != null) {
0622: setValue(sqlP, curField, dummyValue,
0623: modelFieldTypeReader);
0624: }
0625: }
0626: }
0627:
0628: /**
0629: * Get all primary keys from the model entity and bind their values
0630: * to the an SQL statement (SQL-Processor)
0631: *
0632: * @param sqlP
0633: * @param modelEntity
0634: * @param entity
0635: * @param modelFieldTypeReader
0636: * @throws GenericEntityException
0637: */
0638: public static void setPkValues(SQLProcessor sqlP,
0639: ModelEntity modelEntity, GenericEntity entity,
0640: ModelFieldTypeReader modelFieldTypeReader)
0641: throws GenericEntityException {
0642: for (int j = 0; j < modelEntity.getPksSize(); j++) {
0643: ModelField curField = modelEntity.getPk(j);
0644:
0645: // for where clause variables only setValue if not null...
0646: if (entity.dangerousGetNoCheckButFast(curField) != null) {
0647: setValue(sqlP, curField, entity, modelFieldTypeReader);
0648: }
0649: }
0650: }
0651:
0652: public static void getValue(ResultSet rs, int ind,
0653: ModelField curField, GenericEntity entity,
0654: ModelFieldTypeReader modelFieldTypeReader)
0655: throws GenericEntityException {
0656: ModelFieldType mft = modelFieldTypeReader
0657: .getModelFieldType(curField.getType());
0658:
0659: if (mft == null) {
0660: throw new GenericModelException("definition fieldType "
0661: + curField.getType()
0662: + " not found, cannot getValue for field "
0663: + entity.getEntityName() + "." + curField.getName()
0664: + ".");
0665: }
0666: String fieldType = mft.getJavaType();
0667:
0668: try {
0669: // checking to see if the object is null is really only necessary for the numbers
0670: int typeValue = getType(fieldType);
0671: ResultSetMetaData rsmd = rs.getMetaData();
0672: int colType = rsmd.getColumnType(ind);
0673:
0674: if (typeValue <= 4 || typeValue == 10 || typeValue == 11) {
0675: switch (typeValue) {
0676: case 1:
0677: if (java.sql.Types.CLOB == colType) {
0678: // Debug.logInfo("For field " + curField.getName() + " of entity " + entity.getEntityName() + " getString is a CLOB, trying getCharacterStream", module);
0679: // if the String is empty, try to get a text input stream, this is required for some databases for larger fields, like CLOBs
0680:
0681: /*Clob valueClob = rs.getClob(ind);
0682: Reader valueReader = null;
0683: if (valueClob != null) {
0684: valueReader = valueClob.getCharacterStream();
0685: }*/
0686:
0687: Reader valueReader = rs.getCharacterStream(ind);
0688: if (valueReader != null) {
0689: char[] inCharBuffer = new char[CHAR_BUFFER_SIZE];
0690: StringBuffer strBuf = new StringBuffer();
0691: int charsRead = 0;
0692: try {
0693: while ((charsRead = valueReader.read(
0694: inCharBuffer, 0,
0695: CHAR_BUFFER_SIZE)) > 0) {
0696: strBuf.append(inCharBuffer, 0,
0697: charsRead);
0698: }
0699: valueReader.close();
0700: } catch (IOException e) {
0701: throw new GenericEntityException(
0702: "Error reading long character stream for field "
0703: + curField.getName()
0704: + " of entity "
0705: + entity
0706: .getEntityName(),
0707: e);
0708: }
0709: entity.dangerousSetNoCheckButFast(curField,
0710: strBuf.toString());
0711: } else {
0712: entity.dangerousSetNoCheckButFast(curField,
0713: null);
0714: }
0715: } else {
0716: String value = rs.getString(ind);
0717: entity.dangerousSetNoCheckButFast(curField,
0718: value);
0719: }
0720: break;
0721:
0722: case 2:
0723: entity.dangerousSetNoCheckButFast(curField, rs
0724: .getTimestamp(ind));
0725: break;
0726:
0727: case 3:
0728: entity.dangerousSetNoCheckButFast(curField, rs
0729: .getTime(ind));
0730: break;
0731:
0732: case 4:
0733: entity.dangerousSetNoCheckButFast(curField, rs
0734: .getDate(ind));
0735: break;
0736:
0737: case 10:
0738: Object obj = null;
0739: InputStream binaryInput = null;
0740:
0741: byte[] fieldBytes = rs.getBytes(ind);
0742: if (fieldBytes != null && fieldBytes.length > 0) {
0743: binaryInput = new ByteArrayInputStream(
0744: fieldBytes);
0745: }
0746:
0747: if (fieldBytes != null && fieldBytes.length <= 0) {
0748: Debug.logWarning(
0749: "Got bytes back for Object field with length: "
0750: + fieldBytes.length
0751: + " while getting value : "
0752: + curField.getName() + " ["
0753: + curField.getColName() + "] ("
0754: + ind + "): ", module);
0755: }
0756:
0757: //alt 1: binaryInput = rs.getBinaryStream(ind);
0758: //alt 2: Blob blobLocator = rs.getBlob(ind);
0759: //if (blobLocator != null) {
0760: // binaryInput = blobLocator.getBinaryStream();
0761: //}
0762:
0763: if (binaryInput != null) {
0764: ObjectInputStream in = null;
0765: try {
0766: in = new ObjectInputStream(binaryInput);
0767: obj = in.readObject();
0768: } catch (IOException ex) {
0769: throw new GenericDataSourceException(
0770: "Unable to read BLOB data from input stream while getting value : "
0771: + curField.getName() + " ["
0772: + curField.getColName()
0773: + "] (" + ind + "): "
0774: + ex.toString(), ex);
0775: } catch (ClassNotFoundException ex) {
0776: throw new GenericDataSourceException(
0777: "Class not found: Unable to cast BLOB data to an Java object while getting value : "
0778: + curField.getName()
0779: + " ["
0780: + curField.getColName()
0781: + "] ("
0782: + ind
0783: + "): "
0784: + ex.toString(), ex);
0785: } finally {
0786: if (in != null) {
0787: try {
0788: in.close();
0789: } catch (IOException e) {
0790: throw new GenericDataSourceException(
0791: "Unable to close binary input stream while getting value : "
0792: + curField
0793: .getName()
0794: + " ["
0795: + curField
0796: .getColName()
0797: + "] (" + ind
0798: + "): "
0799: + e.toString(), e);
0800: }
0801: }
0802: }
0803: }
0804:
0805: binaryInput = null;
0806: entity.dangerousSetNoCheckButFast(curField, obj);
0807: break;
0808: case 11:
0809: entity.dangerousSetNoCheckButFast(curField, rs
0810: .getBlob(ind));
0811: break;
0812: case 12:
0813: entity.dangerousSetNoCheckButFast(curField, rs
0814: .getClob(ind));
0815: break;
0816: }
0817: } else {
0818: switch (typeValue) {
0819: case 5:
0820: int intValue = rs.getInt(ind);
0821:
0822: if (rs.wasNull()) {
0823: entity.dangerousSetNoCheckButFast(curField,
0824: null);
0825: } else {
0826: entity.dangerousSetNoCheckButFast(curField,
0827: new Integer(intValue));
0828: }
0829: break;
0830:
0831: case 6:
0832: long longValue = rs.getLong(ind);
0833:
0834: if (rs.wasNull()) {
0835: entity.dangerousSetNoCheckButFast(curField,
0836: null);
0837: } else {
0838: entity.dangerousSetNoCheckButFast(curField,
0839: new Long(longValue));
0840: }
0841: break;
0842:
0843: case 7:
0844: float floatValue = rs.getFloat(ind);
0845:
0846: if (rs.wasNull()) {
0847: entity.dangerousSetNoCheckButFast(curField,
0848: null);
0849: } else {
0850: entity.dangerousSetNoCheckButFast(curField,
0851: new Float(floatValue));
0852: }
0853: break;
0854:
0855: case 8:
0856: double doubleValue = rs.getDouble(ind);
0857:
0858: if (rs.wasNull()) {
0859: entity.dangerousSetNoCheckButFast(curField,
0860: null);
0861: } else {
0862: entity.dangerousSetNoCheckButFast(curField,
0863: new Double(doubleValue));
0864: }
0865: break;
0866:
0867: case 9:
0868: boolean booleanValue = rs.getBoolean(ind);
0869:
0870: if (rs.wasNull()) {
0871: entity.dangerousSetNoCheckButFast(curField,
0872: null);
0873: } else {
0874: entity.dangerousSetNoCheckButFast(curField,
0875: new Boolean(booleanValue));
0876: }
0877: break;
0878: }
0879: }
0880: } catch (SQLException sqle) {
0881: throw new GenericDataSourceException(
0882: "SQL Exception while getting value : "
0883: + curField.getName() + " ["
0884: + curField.getColName() + "] (" + ind + ")",
0885: sqle);
0886: }
0887: }
0888:
0889: public static void setValue(SQLProcessor sqlP,
0890: ModelField modelField, GenericEntity entity,
0891: ModelFieldTypeReader modelFieldTypeReader)
0892: throws GenericEntityException {
0893: Object fieldValue = entity
0894: .dangerousGetNoCheckButFast(modelField);
0895:
0896: setValue(sqlP, modelField, entity.getEntityName(), fieldValue,
0897: modelFieldTypeReader);
0898: }
0899:
0900: public static void setValue(SQLProcessor sqlP,
0901: ModelField modelField, String entityName,
0902: Object fieldValue, ModelFieldTypeReader modelFieldTypeReader)
0903: throws GenericEntityException {
0904: ModelFieldType mft = modelFieldTypeReader
0905: .getModelFieldType(modelField.getType());
0906:
0907: if (mft == null) {
0908: throw new GenericModelException(
0909: "GenericDAO.getValue: definition fieldType "
0910: + modelField.getType()
0911: + " not found, cannot setValue for field "
0912: + entityName + "." + modelField.getName()
0913: + ".");
0914: }
0915:
0916: String fieldType = mft.getJavaType();
0917:
0918: if (fieldValue != null) {
0919: if (!ObjectType.instanceOf(fieldValue, fieldType)) {
0920: // this is only an info level message because under normal operation for most JDBC
0921: // drivers this will be okay, but if not then the JDBC driver will throw an exception
0922: // and when lower debug levels are on this should help give more info on what happened
0923: Class fieldClass = fieldValue.getClass();
0924: String fieldClassName = fieldClass.getName();
0925:
0926: if (Debug.verboseOn())
0927: Debug
0928: .logVerbose(
0929: "type of field "
0930: + entityName
0931: + "."
0932: + modelField.getName()
0933: + " is "
0934: + fieldClassName
0935: + ", was expecting "
0936: + mft.getJavaType()
0937: + "; this may "
0938: + "indicate an error in the configuration or in the class, and may result "
0939: + "in an SQL-Java data conversion error. Will use the real field type: "
0940: + fieldClassName
0941: + ", not the definition.",
0942: module);
0943: fieldType = fieldClassName;
0944: }
0945: }
0946:
0947: try {
0948: int typeValue = getType(fieldType);
0949:
0950: switch (typeValue) {
0951: case 1:
0952: String strValue = (String) fieldValue;
0953: sqlP.setValue(strValue);
0954: break;
0955:
0956: case 2:
0957: sqlP.setValue((java.sql.Timestamp) fieldValue);
0958: break;
0959:
0960: case 3:
0961: sqlP.setValue((java.sql.Time) fieldValue);
0962: break;
0963:
0964: case 4:
0965: sqlP.setValue((java.sql.Date) fieldValue);
0966: break;
0967:
0968: case 5:
0969: sqlP.setValue((java.lang.Integer) fieldValue);
0970: break;
0971:
0972: case 6:
0973: sqlP.setValue((java.lang.Long) fieldValue);
0974: break;
0975:
0976: case 7:
0977: sqlP.setValue((java.lang.Float) fieldValue);
0978: break;
0979:
0980: case 8:
0981: sqlP.setValue((java.lang.Double) fieldValue);
0982: break;
0983:
0984: case 9:
0985: sqlP.setValue((java.lang.Boolean) fieldValue);
0986: break;
0987:
0988: case 10:
0989: sqlP.setBinaryStream(fieldValue);
0990: break;
0991:
0992: case 11:
0993: sqlP.setValue((java.sql.Blob) fieldValue);
0994: break;
0995:
0996: case 12:
0997: sqlP.setValue((java.sql.Clob) fieldValue);
0998: break;
0999: }
1000: } catch (SQLException sqle) {
1001: throw new GenericDataSourceException(
1002: "SQL Exception while setting value ("
1003: + modelField.getName() + "): ", sqle);
1004: }
1005: }
1006:
1007: protected static Map fieldTypeMap = new HashMap();
1008: static {
1009: fieldTypeMap.put("java.lang.String", new Integer(1));
1010: fieldTypeMap.put("String", new Integer(1));
1011: fieldTypeMap.put("java.sql.Timestamp", new Integer(2));
1012: fieldTypeMap.put("Timestamp", new Integer(2));
1013: fieldTypeMap.put("java.sql.Time", new Integer(3));
1014: fieldTypeMap.put("Time", new Integer(3));
1015: fieldTypeMap.put("java.sql.Date", new Integer(4));
1016: fieldTypeMap.put("Date", new Integer(4));
1017: fieldTypeMap.put("java.lang.Integer", new Integer(5));
1018: fieldTypeMap.put("Integer", new Integer(5));
1019: fieldTypeMap.put("java.lang.Long", new Integer(6));
1020: fieldTypeMap.put("Long", new Integer(6));
1021: fieldTypeMap.put("java.lang.Float", new Integer(7));
1022: fieldTypeMap.put("Float", new Integer(7));
1023: fieldTypeMap.put("java.lang.Double", new Integer(8));
1024: fieldTypeMap.put("Double", new Integer(8));
1025: fieldTypeMap.put("java.lang.Boolean", new Integer(9));
1026: fieldTypeMap.put("Boolean", new Integer(9));
1027: fieldTypeMap.put("java.lang.Object", new Integer(10));
1028: fieldTypeMap.put("Object", new Integer(10));
1029: fieldTypeMap.put("java.sql.Blob", new Integer(11));
1030: fieldTypeMap.put("Blob", new Integer(11));
1031: fieldTypeMap.put("java.sql.Clob", new Integer(12));
1032: fieldTypeMap.put("Clob", new Integer(12));
1033: }
1034:
1035: public static int getType(String fieldType)
1036: throws GenericNotImplementedException {
1037: Integer val = (Integer) fieldTypeMap.get(fieldType);
1038:
1039: if (val == null) {
1040: throw new GenericNotImplementedException("Java type "
1041: + fieldType + " not currently supported. Sorry.");
1042: }
1043: return val.intValue();
1044: }
1045:
1046: public static void addValue(StringBuffer buffer, ModelField field,
1047: Object value, List params) {
1048: if (field != null) {
1049: buffer.append('?');
1050: } else {
1051: buffer.append('\'').append(value).append('\'');
1052: }
1053: if (field != null && params != null)
1054: params.add(new EntityConditionParam(field, value));
1055: }
1056: }
|