1 64 65 package com.jcorporate.expresso.core.dbobj; 66 67 import com.jcorporate.expresso.core.controller.ControllerRequest; 68 import com.jcorporate.expresso.core.dataobjects.DataException; 69 import com.jcorporate.expresso.core.dataobjects.DataFieldMetaData; 70 import com.jcorporate.expresso.core.dataobjects.jdbc.FieldRangeParser; 71 import com.jcorporate.expresso.core.db.DBConnection; 72 import com.jcorporate.expresso.core.db.DBConnectionPool; 73 import com.jcorporate.expresso.core.db.DBException; 74 import com.jcorporate.expresso.core.misc.ConfigJdbc; 75 import com.jcorporate.expresso.core.misc.ConfigManager; 76 import com.jcorporate.expresso.core.misc.ConfigurationException; 77 import com.jcorporate.expresso.core.misc.StringUtil; 78 import com.jcorporate.expresso.core.security.filters.Filter; 79 import com.jcorporate.expresso.kernel.util.ClassLocator; 80 import com.jcorporate.expresso.kernel.util.FastStringBuffer; 81 import org.apache.log4j.Logger; 82 83 import java.math.BigDecimal ; 84 import java.util.ArrayList ; 85 import java.util.Date ; 86 import java.util.Enumeration ; 87 import java.util.HashMap ; 88 import java.util.Hashtable ; 89 import java.util.Iterator ; 90 import java.util.List ; 91 import java.util.StringTokenizer ; 92 import java.util.Vector ; 93 94 95 121 public class MultiDBObject { 122 123 131 private String ignoreInWhereClause = ""; 132 133 138 private Vector originalJoins = new Vector (); 139 140 148 private String customFromClause = null; 149 152 155 private boolean selectDistinct = false; 156 157 160 private HashMap attributes = null; 161 162 168 transient protected int offsetRecord = 0; 169 170 175 private boolean appendCustomWhereClause = false; 176 177 180 protected static final int INNER_JOIN = 0; 181 protected static final int RIGHT_JOIN = 1; 182 protected static final int LEFT_JOIN = 2; 183 184 187 protected static final String SHORT_NAME = "shortName"; 188 189 192 private String fromClause = null; 193 194 198 private boolean shortNameAsAlias = false; 199 200 207 public Object getAttribute(String attribName) { 208 if (attributes != null) { 209 return attributes.get(attribName); 210 } else { 211 return null; 212 } 213 } 214 215 216 223 public synchronized void setAttribute(String attribName, 224 Object attribValue) { 225 if (attributes == null) { 226 attributes = new HashMap (); 227 } 228 229 attributes.put(attribName, attribValue); 230 } 231 232 233 240 public int getMaxRecords() { 241 return maxRecords; 242 } 243 244 260 public synchronized void setOffsetRecord(int newOffset) 261 throws DBException { 262 if (newOffset < 0) { 263 throw new DBException("Offset records can't be less than 0"); 264 } 265 266 offsetRecord = newOffset; 267 } 268 269 280 public int getOffsetRecord() { 281 return offsetRecord; 282 } 283 284 292 public synchronized void setCustomFromClause(String newCustomFrom) { 293 customFromClause = newCustomFrom; 294 } 295 296 301 public String getCustomFromClause() { 302 return customFromClause; 303 } 304 305 315 public boolean buildFromClause() throws DBException { 316 boolean success = false; 317 FastStringBuffer fsb = new FastStringBuffer(256); 318 int dboCount = myDBObjects.size(); 319 320 try { 321 if (customFromClause != null && 323 customFromClause.trim().length() > 0) { 324 fromClause = customFromClause; 326 success = true; 327 } 328 else if (!originalJoins.isEmpty()) { 330 if (!originalRelations.isEmpty()) { 331 throw new DBException(thisClass + "count()" + 332 "You cannot mix set???Join() with setForeignKey() definitions." + 333 "Use setInnerJoin() instead of setForeignKey()."); 334 } 335 336 fromClause = null; 338 String oneJoin = null; 339 340 for (Enumeration n = originalJoins.elements(); 341 n.hasMoreElements();) { 342 oneJoin = (String ) n.nextElement(); 343 344 StringTokenizer stk = new StringTokenizer (oneJoin, "|"); 345 String leftDbo = stk.nextToken(); 346 String leftField = stk.nextToken(); 347 String rightDbo = stk.nextToken(); 348 String rightField = stk.nextToken(); 349 String joinTyp = stk.nextToken().toLowerCase(); 350 351 if ("left".equals(joinTyp)) { 352 buildJoin(leftDbo, leftField, rightDbo, rightField, LEFT_JOIN); 353 } else if ("inner".equals(joinTyp)) { 354 buildJoin(leftDbo, leftField, rightDbo, rightField, INNER_JOIN); 355 } else if ("right".equals(joinTyp)) { 356 buildJoin(leftDbo, leftField, rightDbo, rightField, RIGHT_JOIN); 357 } else { 358 throw new DBException(thisClass + "count()" + 359 "Missing join-type in '" + oneJoin + "'"); 360 } 361 } 362 success = true; 363 } 364 else if (!originalRelations.isEmpty() || dboCount == 1) { 366 boolean needComma = false; 372 DBObject oneObj = null; 373 374 for (Enumeration eachObj = myDBObjects.elements(); 375 eachObj.hasMoreElements();) { 376 oneObj = (DBObject) eachObj.nextElement(); 377 378 if (needComma) { 379 fsb.append(","); 380 } 381 382 String targetTable = oneObj.getJDBCMetaData().getTargetSQLTable(oneObj.getDataContext()); 383 String tableName = getTableName(oneObj); 384 fsb.append(targetTable); 385 if (!targetTable.equals(tableName)) { 386 fsb.append(" AS " + tableName); 387 } 388 needComma = true; 389 } 390 391 fromClause = fsb.toString(); 392 success = true; 393 } 394 else { 396 boolean needComma = false; 398 399 for (Enumeration eachObj = myDBObjects.elements(); 400 eachObj.hasMoreElements();) { 401 DBObject oneObj = (DBObject) eachObj.nextElement(); 402 403 if (needComma) { 404 fsb.append(","); 405 } 406 407 String targetTable = oneObj.getJDBCMetaData().getTargetSQLTable(oneObj.getDataContext()); 408 String tableName = getTableName(oneObj); 409 fsb.append(targetTable); 410 if (!targetTable.equals(tableName)) { 411 fsb.append(" AS " + tableName); 412 } 413 needComma = true; 414 } 415 416 fromClause = fsb.toString(); 417 success = true; 418 } 419 } catch (Throwable t) { 420 throw new DBException(t); 421 } finally { 422 fsb.release(); 423 } 424 425 return (success); 426 } 427 430 431 437 public synchronized int count(String expr) 438 throws DBException { 439 490 492 503 504 DBConnectionPool myPool = null; 505 DBConnection myConnection = null; 506 507 try { 508 if (localConnection != null) { 509 myConnection = localConnection; 510 } else { 511 myPool = DBConnectionPool.getInstance(getDBName()); 512 myConnection = myPool.getConnection("com.jcorporate.expresso.core.dbobj.DBObject"); 513 } 514 515 if (recordSet == null) { 516 String myName = (thisClass + "count()"); 517 throw new DBException(myName + 518 ":Database object not correctly initialized"); 519 } 520 521 recordSet.clear(); 522 523 FastStringBuffer myStatement = new FastStringBuffer(256); 524 myStatement.append("SELECT "); 525 526 if (selectDistinct) { 527 myStatement.append(" DISTINCT "); 528 } 529 if (StringUtil.isBlankOrNull(expr)) { 530 expr = "*"; 531 } 532 myStatement.append("COUNT(" + expr + ") "); 533 534 542 568 myStatement.append(" FROM "); 569 if (buildFromClause() && 570 fromClause != null && 571 fromClause.trim().length() > 0) { 572 myStatement.append(fromClause); 573 } else { 574 throw new DBException(thisClass + "count()" + 575 " :Building of FROM clause failed."); 576 } 577 580 String whereClause; 581 if (customWhereClause != null) { 582 if (appendCustomWhereClause) { 583 whereClause = buildWhereClause(true) + " AND " + customWhereClause; 584 } else { 585 whereClause = " WHERE " + customWhereClause; 586 } 587 } else { 588 whereClause = buildWhereClause(true); 589 } 590 591 myStatement.append(whereClause); 592 593 appendCustomWhereClause = false; 594 595 if (log.isDebugEnabled()) { 596 log.debug("Executing " + myStatement.toString()); 597 } 598 599 myConnection.execute(myStatement.toString()); 600 601 if (myConnection.next()) { 602 return myConnection.getInt(1); 603 } 604 } finally { 605 if (localConnection == null) { 606 myPool.release(myConnection); 607 } 608 } 609 610 611 return 0; 612 } 613 614 620 public synchronized int count() 621 throws DBException { 622 return count(""); 623 } 624 625 626 663 protected String makeLimitationStub(DBConnection theConnection) { 664 String limit = theConnection.getLimitationSyntax(); 665 int offset = this.getOffsetRecord(); 666 int maxrec = this.getMaxRecords(); 667 int endrec = offset + maxrec - 1; 668 limit = StringUtil.replace(limit, "%offset%", Integer.toString(offset)); 669 limit = StringUtil.replace(limit, "%maxrecords%", 670 Integer.toString(maxrec)); 671 672 limit = StringUtil.replace(limit, "%endrecord%", 674 Integer.toString(endrec)); 675 676 return limit; 677 } 678 679 680 private static final String thisClass = MultiDBObject.class.getName() + "."; 681 682 686 private Hashtable myDBObjects = new Hashtable (); 687 688 692 private Vector relations = new Vector (); 693 private String dbName = null; 694 695 701 private boolean caseSensitiveQuery = true; 702 703 706 private Vector sortKeys = new Vector (); 707 708 711 private List recordSet = new ArrayList (); 712 713 717 private String customWhereClause = null; 718 719 722 private Vector originalRelations = new Vector (); 723 724 728 protected DBConnection localConnection = null; 729 730 733 protected int maxRecords = 0; 734 private static Logger log = Logger.getLogger(MultiDBObject.class); 735 736 739 public MultiDBObject() 740 throws DBException { 741 setupFields(); 742 } 743 744 747 public MultiDBObject(ControllerRequest request) 748 throws DBException { 749 this(); 750 setDBName(request.getDataContext()); 751 } 752 753 763 public void addDBObj(String dbobjClassName, String shortName) 764 throws DBException { 765 String myName = thisClass + "addDBObj(String, String)"; 766 767 if (StringUtil.notNull(dbobjClassName).equals("")) { 768 throw new DBException(myName + ":Must specify a class name"); 769 } 770 if (StringUtil.notNull(shortName).equals("")) { 771 throw new DBException(myName + ":Must specify a short name"); 772 } 773 774 DBObject oneDBObj = null; 775 776 try { 777 Class c = ClassLocator.loadClass(dbobjClassName); 778 oneDBObj = (DBObject) c.newInstance(); 779 } catch (ClassNotFoundException cn) { 780 throw new DBException(myName + ":DBObject '" + dbobjClassName + 781 "' not found", cn); 782 } catch (InstantiationException ie) { 783 throw new DBException(myName + ":DBObject '" + dbobjClassName + 784 "' cannot be instantiated", ie); 785 } catch (IllegalAccessException iae) { 786 throw new DBException(myName + 787 ":Illegal access loading DBObject '" + 788 dbobjClassName + "'", iae); 789 } 790 791 addDBObj(oneDBObj, shortName); 792 } 793 794 public void addDBObj(DBObject oneDBObj, String shortName) 795 throws DBException { 796 StringUtil.assertNotBlank(shortName, "Short name cannot be blank here"); 797 oneDBObj.setAttribute(SHORT_NAME, shortName); 798 myDBObjects.put(shortName, oneDBObj); 799 800 if (getDBName() == null) { 801 setDBName(oneDBObj.getDataContext()); 802 } 803 804 805 oneDBObj.setDataContext(getDBName()); 806 807 if (!oneDBObj.getDataContext().equals(getDBName())) { 808 throw new DBException("DB Object '" + 809 oneDBObj.getClass().getName() + 810 "' was mapped to db/context '" + 811 oneDBObj.getDataContext() + 812 "', but this MultiDBObject is in context '" + 813 getDBName() + "'"); 814 } 815 } 816 817 826 public String buildWhereClause(boolean useAllFields) 827 throws DBException { 828 FastStringBuffer fsb = FastStringBuffer.getInstance(); 829 try { 830 return buildWhereClauseBuffer(useAllFields, fsb).toString(); 831 } finally { 832 fsb.release(); 833 } 834 } 835 836 847 protected String buildWhereClauseBuffer(boolean useAllFields, FastStringBuffer myStatement) 848 throws DBException { 849 return buildWhereClauseBuffer(useAllFields, myStatement, " ").toString(); 850 } 851 854 870 protected String buildWhereClauseBuffer(boolean useAllFields, FastStringBuffer myStatement, String dboAlias) 871 throws DBException { 872 873 874 Vector fields = new Vector (); 875 DBObject oneObj = null; 876 String fieldName = null; 877 Hashtable byTableName = new Hashtable (); 878 879 if (useAllFields) { 880 for (Enumeration eachObj = myDBObjects.elements(); 881 eachObj.hasMoreElements();) { 882 oneObj = (DBObject) eachObj.nextElement(); 883 byTableName.put(getTableName(oneObj), oneObj); 884 885 String thisDbo = (String ) oneObj.getAttribute(SHORT_NAME); 896 897 if (dboAlias.trim().length() > 0) { 898 if (!thisDbo.equals(dboAlias)) { 899 continue; 900 } 901 } else if (ignoreInWhereClause.indexOf("," + thisDbo + ",") >= 0) { 902 continue; 903 } 904 907 for (Iterator i = oneObj.getMetaData().getFieldListArray().iterator(); i.hasNext();) { 908 fieldName = (String ) i.next(); 909 910 if (!oneObj.getMetaData().getFieldMetadata(fieldName).isVirtual()) { 911 fields.addElement(getTableName(oneObj) + "." + 912 fieldName); 913 } 914 } 915 } 916 } else { 917 for (Enumeration eachObj = myDBObjects.elements(); 918 eachObj.hasMoreElements();) { 919 oneObj = (DBObject) eachObj.nextElement(); 920 921 String thisDbo = (String ) oneObj.getAttribute(SHORT_NAME); 932 933 if (dboAlias.trim().length() > 0) { 934 if (!thisDbo.equals(dboAlias)) { 935 continue; 936 } 937 } else if (ignoreInWhereClause.indexOf("," + thisDbo + ",") >= 0) { 938 continue; 939 } 940 943 for (Iterator i = oneObj.getKeyFieldListIterator(); 944 i.hasNext();) { 945 fieldName = (String ) i.next(); 946 947 if (!oneObj.getMetaData().getFieldMetadata(fieldName).isVirtual()) { 948 fields.addElement(getTableName(oneObj) + "." + 949 fieldName); 950 } 951 } 952 } 953 } 954 955 956 957 958 boolean addWhere = true; 959 boolean addAnd = false; 960 String oneFieldName = null; 961 String oneTableName = null; 962 String oneFullName = null; 963 String oneFieldValue = null; 964 boolean skipText = false; 965 966 try { 967 ConfigJdbc myConfig = ConfigManager.getJdbcRequired(getDBName()); 968 skipText = myConfig.skipText(); 969 } catch (ConfigurationException ce) { 970 throw new DBException(ce); 971 } 972 973 boolean skipField = false; 974 975 for (Enumeration fieldsToUse = fields.elements(); 976 fieldsToUse.hasMoreElements();) { 977 oneFullName = (String ) fieldsToUse.nextElement(); 978 979 StringTokenizer stk = new StringTokenizer (oneFullName, "."); 980 int stkCount = stk.countTokens(); 981 if (stkCount == 2) { 982 oneTableName = stk.nextToken(); 983 oneFieldName = stk.nextToken(); 984 } else if (stkCount == 3) { 985 String oneSchemaName = stk.nextToken(); 986 oneTableName = stk.nextToken(); 987 oneFieldName = stk.nextToken(); 988 oneTableName = oneSchemaName + "." + oneTableName; 989 } 990 991 oneObj = (DBObject) byTableName.get(oneTableName); 992 skipField = false; 993 1001 1002 1005 1006 oneFieldValue = StringUtil.notNull(oneObj.getFieldData(oneFieldName)); 1007 1010 String rangeString = oneObj.denotesRange(oneFieldValue); 1011 1012 if (!oneFieldValue.equals("")) { 1013 oneFieldValue = oneObj.quoteIfNeeded(oneFieldName, rangeString); 1014 } 1015 if (oneFieldValue.equals("")) { 1016 skipField = true; 1017 } 1018 if (oneFieldValue == null) { 1019 skipField = true; 1020 } 1021 if (oneFieldValue.equals("\'\'")) { 1022 skipField = true; 1023 } 1024 if ((oneObj.getMetaData().getType(oneFieldName).equals("text")) && (skipText)) { 1025 skipField = true; 1026 } 1027 if (!skipField) { 1028 String unalteredFieldValue = oneObj.getDataField(oneFieldName).asString(); 1030 if (rangeString != null) { 1031 FieldRangeParser rangeParser = new FieldRangeParser(); 1032 boolean valid = rangeParser.isValidRange(oneObj.getFieldMetaData(oneFieldName), 1033 unalteredFieldValue); 1034 if (!valid) { 1035 throw new DBException("Invalid field range value: " + unalteredFieldValue); 1036 } 1037 } else if (oneObj.containsWildCards(oneFieldValue)) { 1038 Object origValue = oneObj.getDataField(oneFieldName).getValue(); 1039 1040 String [] wildcards = null; 1041 wildcards = (String []) oneObj.getConnectionPool().getWildCardsList().toArray(new String [0]); 1042 Filter filter = new Filter(wildcards, wildcards); 1043 String valueWithoutWildCards = filter.stripFilter(unalteredFieldValue); 1044 if (!valueWithoutWildCards.equals("")) { 1046 oneObj.getDataField(oneFieldName).setValue(valueWithoutWildCards); 1047 oneObj.getDataField(oneFieldName).checkValue(); 1048 oneObj.getDataField(oneFieldName).setValue(origValue); 1049 } 1050 } else { 1051 oneObj.getDataField(oneFieldName).checkValue(); 1052 } 1053 1054 1055 if (addWhere) { 1056 myStatement.append(" WHERE "); 1057 addWhere = false; 1058 } 1059 if (addAnd) { 1060 myStatement.append(" AND "); 1061 } 1062 if (oneObj.containsWildCards(oneFieldValue)) { 1063 if (caseSensitiveQuery) { 1064 myStatement.append(getTableName(oneObj) + "." + 1065 oneFieldName); 1066 myStatement.append(" LIKE "); 1067 myStatement.append(oneFieldValue); 1068 } else { 1069 myStatement.append("UPPER("); 1070 myStatement.append(getTableName(oneObj) + "." + 1071 oneFieldName); 1072 myStatement.append(") LIKE "); 1073 myStatement.append(oneFieldValue.toUpperCase()); 1074 } 1075 } else if (rangeString != null) { 1076 myStatement.append(getTableName(oneObj) + "." + 1077 oneFieldName); 1078 myStatement.append(" " + rangeString + " "); 1079 myStatement.append(oneFieldValue); 1080 } else { 1081 if (caseSensitiveQuery) { 1082 myStatement.append(getTableName(oneObj) + "." + 1083 oneFieldName); 1084 myStatement.append(" = "); 1085 myStatement.append(oneFieldValue); 1086 } else { 1087 myStatement.append("UPPER("); 1088 myStatement.append(getTableName(oneObj) + "." + 1089 oneFieldName); 1090 myStatement.append(") = "); 1091 myStatement.append(oneFieldValue.toUpperCase()); 1092 } 1093 } 1094 1095 addAnd = true; 1096 } 1097 1098 1099 } 1100 1101 1102 boolean needAnd = false; 1103 1104 1116 1117 if (originalJoins.isEmpty()) { 1123 String oneRelation = null; 1124 1125 for (Enumeration e = relations.elements(); e.hasMoreElements();) { 1126 1130 if (addWhere) { 1131 myStatement.append(" WHERE "); 1132 addWhere = false; 1133 } else { 1134 needAnd = true; 1135 } 1136 1137 oneRelation = (String ) e.nextElement(); 1138 1139 if (needAnd) { 1140 myStatement.append(" AND "); 1141 } 1142 1143 myStatement.append(oneRelation); 1144 needAnd = true; 1145 } 1146 } 1147 1150 if (log.isDebugEnabled()) { 1151 log.debug(myStatement.toString()); 1152 } 1153 1154 return myStatement.toString(); 1155 } 1156 1157 1158 1166 public void clear() 1167 throws com.jcorporate.expresso.core.db.DBException { 1168 DBObject oneObj = null; 1169 1170 for (Enumeration eachObj = myDBObjects.elements(); 1171 eachObj.hasMoreElements();) { 1172 oneObj = (DBObject) eachObj.nextElement(); 1173 oneObj.clear(); 1174 } 1175 1176 1179 fromClause = null; 1180 1181 } 1182 1183 1184 1190 public synchronized String getDBName() { 1191 return dbName; 1192 } 1193 1194 1200 public synchronized String getDataContext() { 1201 return dbName; 1202 } 1203 1204 1205 1221 public DBObject getDBObject(String shortName) 1222 throws DBException { 1223 1224 DBObject oneObj = (DBObject) myDBObjects.get(shortName); 1225 if (oneObj == null) { 1226 String myName = thisClass + "getDBObject(String)"; 1227 throw new DBException(myName + ":No such object as '" 1228 + shortName + "'"); 1229 } 1230 return oneObj; 1231 } 1232 1233 1234 1243 public String getField(String shortName, String fieldName) 1244 throws DBException { 1245 DBObject oneObj = (DBObject) myDBObjects.get(shortName); 1246 1247 if (oneObj == null) { 1248 String myName = thisClass + "getField(String, String)"; 1249 throw new DBException(myName + ":No such object as '" + shortName + 1250 "'"); 1251 } 1252 1253 return oneObj.getField(fieldName); 1254 } 1255 1256 1257 private DBObject getByShortName(String shortName) 1258 throws DBException { 1259 StringUtil.assertNotBlank(shortName, "Short name may not be blank"); 1260 1261 DBObject oneObj = (DBObject) myDBObjects.get(shortName); 1262 1263 if (oneObj == null) { 1264 throw new DBException("No such object as '" + shortName + "'"); 1265 } 1266 1267 return oneObj; 1268 } 1269 1270 public String getFieldDecimalFormatted(String shortName, String fieldName, 1271 String formatPattern) 1272 throws DBException { 1273 return getByShortName(shortName).getFieldDecimalFormatted(fieldName, 1274 formatPattern); 1275 } 1276 1277 1278 public float getFieldFloat(String shortName, String fieldName) 1279 throws DBException { 1280 return getByShortName(shortName).getFieldFloat(fieldName); 1281 } 1282 1283 1288 public double getFieldDouble(String shortName, String fieldName) 1289 throws DBException { 1290 return getByShortName(shortName).getFieldDouble(fieldName); 1291 } 1292 1293 1298 public BigDecimal getFieldBigDecimal(String shortName, String fieldName) 1299 throws DBException { 1300 return getByShortName(shortName).getFieldBigDecimal(fieldName); 1301 } 1302 1303 public Date getFieldDate(String shortName, String fieldName) 1304 throws DBException { 1305 return getByShortName(shortName).getFieldDate(fieldName); 1306 } 1307 1308 1309 public int getFieldInt(String shortName, String fieldName) 1310 throws DBException { 1311 return getByShortName(shortName).getFieldInt(fieldName); 1312 } 1313 1314 public long getFieldLong(String shortName, String fieldName) 1315 throws DBException { 1316 return getByShortName(shortName).getFieldLong(fieldName); 1317 } 1318 1319 1325 protected MultiDBObject getThisMultiDBObj() 1326 throws DBException { 1327 MultiDBObject newObj = new MultiDBObject(); 1328 newObj.setDBName(getDBName()); 1329 1330 String oneKey = null; 1331 DBObject oneDBObj = null; 1332 1333 for (Enumeration ek = myDBObjects.keys(); ek.hasMoreElements();) { 1334 oneKey = (String ) ek.nextElement(); 1335 oneDBObj = (DBObject) myDBObjects.get(oneKey); 1336 newObj.addDBObj(oneDBObj.newInstance(), oneKey); 1337 } 1338 1339 String oneRelation = null; 1340 1341 for (Enumeration er = originalRelations.elements(); 1342 er.hasMoreElements();) { 1343 oneRelation = (String ) er.nextElement(); 1344 1345 StringTokenizer stk = new StringTokenizer (oneRelation, "|"); 1346 newObj.setForeignKey(stk.nextToken(), stk.nextToken(), 1347 stk.nextToken(), stk.nextToken()); 1348 } 1349 1350 String oneJoin = null; 1354 1355 for (Enumeration n = originalJoins.elements(); 1356 n.hasMoreElements();) { 1357 oneJoin = (String ) n.nextElement(); 1358 1359 StringTokenizer stk = new StringTokenizer (oneJoin, "|"); 1360 String leftDbo = stk.nextToken(); 1361 String leftField = stk.nextToken(); 1362 String rightDbo = stk.nextToken(); 1363 String rightField = stk.nextToken(); 1364 String joinTyp = stk.nextToken().toLowerCase(); 1365 1366 if ("left".equals(joinTyp)) { 1367 newObj.setLeftJoin(leftDbo, leftField, rightDbo, rightField); 1368 } else if ("inner".equals(joinTyp)) { 1369 newObj.setInnerJoin(leftDbo, leftField, rightDbo, rightField); 1370 } else if ("right".equals(joinTyp)) { 1371 newObj.setRightJoin(leftDbo, leftField, rightDbo, rightField); 1372 } 1373 } 1374 1377 return newObj; 1378 } 1379 1380 1388 public synchronized List searchAndRetrieveList(String sortKeyString) throws DBException { 1389 1390 sortKeys.clear(); 1391 if (sortKeyString != null) { 1392 StringTokenizer stk = new StringTokenizer (sortKeyString, "|"); 1393 while (stk.hasMoreTokens()) { 1394 sortKeys.addElement(stk.nextToken()); 1395 } 1396 } 1397 1398 return searchAndRetrieveList(); 1399 } 1400 1401 1407 public synchronized List searchAndRetrieveList() throws DBException { 1408 boolean needComma = false; 1409 DBObject oneObj = null; 1410 1411 HashMap rtrvListByTable = new HashMap (); 1412 1413 DBConnectionPool myPool = null; 1414 DBConnection myConnection = null; 1415 1416 try { 1417 if (localConnection != null) { 1418 myConnection = localConnection; 1419 } else { 1420 myPool = DBConnectionPool.getInstance(getDBName()); 1421 myConnection = myPool.getConnection("com.jcorporate.expresso.core.dbobj.DBObject"); 1422 } 1423 1424 if (recordSet == null) { 1425 String myName = (thisClass + "searchAndRetrieve()"); 1426 throw new DBException(myName + 1427 ":Database object not correctly initialized"); 1428 } 1429 1430 recordSet.clear(); 1431 1432 String fieldName = null; 1433 FastStringBuffer myStatement = new FastStringBuffer(256); 1434 myStatement.append("SELECT "); 1435 1436 if (myConnection.getLimitationPosition() == DBConnection.LIMITATION_AFTER_SELECT && 1437 (offsetRecord > 0 || maxRecords > 0)) { 1438 1439 String limitStub = makeLimitationStub(myConnection); 1441 1442 myStatement.append(" "); 1443 myStatement.append(limitStub); 1444 myStatement.append(" "); 1445 } 1446 1447 if (selectDistinct) { 1448 myStatement.append(" "); 1449 myStatement.append("DISTINCT"); 1450 myStatement.append(" "); 1451 } 1452 1453 for (Enumeration eachObj = myDBObjects.elements(); 1454 eachObj.hasMoreElements();) { 1455 oneObj = (DBObject) eachObj.nextElement(); 1456 1457 ArrayList retrievedFieldList = (ArrayList ) rtrvListByTable.get(getTableName(oneObj)); 1458 if (retrievedFieldList == null) { 1459 retrievedFieldList = new ArrayList (); 1460 rtrvListByTable.put(getTableName(oneObj), retrievedFieldList); 1461 } 1462 1463 if (oneObj.anyFieldsDistinct) { 1464 String oneFieldName = null; 1465 for (Iterator i = oneObj.getDistinctFieldArrayList().iterator(); 1466 i.hasNext(); 1467 ) { 1468 oneFieldName = (String ) i.next(); 1469 if (needComma) { 1470 myStatement.append(", "); 1471 } 1472 myStatement.append(" "); 1473 myStatement.append(myPool.getDistinctRowsetKeyword()); 1474 myStatement.append(" "); 1475 myStatement.append(selectFieldString(oneObj, oneFieldName)); 1476 retrievedFieldList.add(oneFieldName); 1477 needComma = true; 1478 } 1479 } else if (oneObj.anyFieldsToRetrieveMulti) { 1480 String oneFieldName = null; 1481 for (Iterator i = oneObj.getFieldsToRetrieveIterator(); 1482 i.hasNext(); 1483 ) { 1484 oneFieldName = (String ) i.next(); 1485 if (needComma) { 1486 myStatement.append(", "); 1487 } 1488 myStatement.append(selectFieldString(oneObj, oneFieldName)); 1489 retrievedFieldList.add(oneFieldName); 1490 needComma = true; 1491 } 1492 } else { 1493 for (Iterator i = oneObj.getMetaData().getFieldListArray().iterator(); 1494 i.hasNext(); 1495 ) { 1496 fieldName = (String ) i.next(); 1497 DataFieldMetaData metaData = 1498 oneObj.getFieldMetaData(fieldName); 1499 1500 if (!metaData.isVirtual() 1501 && !metaData.isBinaryObjectType()) { 1502 if (needComma) { 1503 myStatement.append(", "); 1504 } 1505 1506 myStatement.append(selectFieldString(oneObj, fieldName)); 1507 retrievedFieldList.add(fieldName); 1508 needComma = true; 1509 } 1510 1511 1512 } 1513 1514 1515 } 1516 } 1517 1518 myStatement.append(" FROM "); 1519 if (buildFromClause() && 1520 fromClause != null && 1521 fromClause.trim().length() > 0) { 1522 myStatement.append(fromClause); 1523 } else { 1524 throw new DBException(thisClass + "count()" + 1525 " :Building of FROM clause failed."); 1526 } 1527 1530 if (myConnection.getLimitationPosition() == DBConnection.LIMITATION_AFTER_TABLE && 1531 (offsetRecord > 0 || maxRecords > 0)) { 1532 1533 String limitStub = makeLimitationStub(myConnection); 1535 myStatement.append(" "); 1536 myStatement.append(limitStub); 1537 myStatement.append(" "); 1538 } 1539 1540 String whereClause; 1541 if (customWhereClause != null) { 1542 if (appendCustomWhereClause) { 1543 whereClause = buildWhereClause(true) + " AND " + customWhereClause; 1544 } else { 1545 whereClause = " WHERE " + customWhereClause; 1546 } 1547 } else { 1548 whereClause = buildWhereClause(true); 1549 } 1550 1551 myStatement.append(whereClause); 1552 1553 appendCustomWhereClause = false; 1554 1555 if (myConnection.getLimitationPosition() == DBConnection.LIMITATION_AFTER_WHERE && 1556 (offsetRecord > 0 || maxRecords > 0)) { 1557 1558 String limitStub = makeLimitationStub(myConnection); 1560 1561 if (whereClause.length() > 0) { 1562 myStatement.append(" AND"); 1563 } 1564 1565 myStatement.append(" "); 1566 myStatement.append(limitStub); 1567 myStatement.append(" "); 1568 } 1569 1570 1571 if (sortKeys.size() > 0) { 1572 myStatement.append(" ORDER BY "); 1573 1574 boolean needComma2 = false; 1575 1576 for (Enumeration e = sortKeys.elements(); e.hasMoreElements();) { 1577 if (needComma2) { 1578 myStatement.append(", "); 1579 } 1580 1581 myStatement.append((String ) e.nextElement()); 1582 needComma2 = true; 1583 } 1584 if (myConnection.getLimitationPosition() == DBConnection.LIMITATION_AFTER_ORDER_BY && 1585 (offsetRecord > 0 || maxRecords > 0)) { 1586 myStatement.append(" "); 1587 myStatement.append(makeLimitationStub(myConnection)); 1588 } 1589 } 1590 1591 if (log.isDebugEnabled()) { 1592 log.debug("Executing " + myStatement.toString()); 1593 } 1594 1595 myConnection.execute(myStatement.toString()); 1596 1597 int returnRecordCount = 0; 1598 int loopCount = 0; 1599 while (myConnection.next()) { 1600 loopCount++; 1601 1602 if (loopCount <= offsetRecord && offsetRecord > 0 && 1605 myConnection.getLimitationPosition() == DBConnection.LIMITATION_DISABLED) { 1606 continue; 1607 } 1608 1609 returnRecordCount++; 1610 1611 if ((returnRecordCount > maxRecords) && (maxRecords > 0)) { 1613 break; 1614 } 1615 1616 1617 if (log.isDebugEnabled()) { 1618 log.debug("Returning row " + loopCount); 1619 } 1620 1621 MultiDBObject myObj = getThisMultiDBObj(); 1622 String oneFieldValue = null; 1623 int i = 1; 1624 1625 for (Enumeration eachObj = myDBObjects.elements(); 1626 eachObj.hasMoreElements();) { 1627 oneObj = (DBObject) eachObj.nextElement(); 1628 1629 ArrayList retrievedFieldList = (ArrayList ) rtrvListByTable.get(getTableName(oneObj)); 1630 if (retrievedFieldList == null) { 1632 retrievedFieldList = new ArrayList (); 1633 } 1634 for (Iterator it = retrievedFieldList.listIterator(); 1635 it.hasNext();) { 1636 fieldName = (String ) it.next(); 1637 DataFieldMetaData metaData = oneObj.getFieldMetaData(fieldName); 1638 1639 if (!metaData.isVirtual() && !metaData.isBinaryObjectType()) { 1640 try { 1641 oneFieldValue = myConnection.getString(i); 1642 } catch (DBException de) { 1643 String myName = (thisClass + "searchAndRetrieve()"); 1644 throw new DBException(myName + 1645 ":Error retrieving field '" + 1646 getTableName(oneObj) + 1647 "." + fieldName + "'", 1648 de); 1649 } 1650 1651 i++; 1652 1653 if (log.isDebugEnabled()) { 1654 log.debug("Setting " + 1655 getTableName(oneObj) + "." + 1656 fieldName + " to " + oneFieldValue); 1657 } 1658 1659 myObj.setField((String ) oneObj.getAttribute(SHORT_NAME), 1660 fieldName, oneFieldValue); 1661 } 1662 } 1663 } 1664 1665 1666 myObj.setDBName(getDBName()); 1667 recordSet.add(myObj); 1668 } 1669 1670 1671 } finally { 1672 if (localConnection == null) { 1673 myPool.release(myConnection); 1674 } 1675 } 1676 1677 return recordSet; 1678 } 1679 1680 1697 public void setCaseSensitiveQuery(boolean isCaseSensitiveQuery) { 1698 caseSensitiveQuery = isCaseSensitiveQuery; 1699 } 1700 1701 1712 public synchronized void setCustomWhereClause(String newCustomWhere) { 1713 setCustomWhereClause(newCustomWhere, false); 1714 } 1715 1716 1727 public synchronized void setCustomWhereClause(String newCustomWhere, boolean append) { 1728 customWhereClause = newCustomWhere; 1729 appendCustomWhereClause = append; 1730 } 1731 1732 1739 public String getCustomWhereClause() { 1740 return customWhereClause; 1741 } 1742 1743 1749 public synchronized void setAppendCustomWhereClause(boolean newValue) { 1750 appendCustomWhereClause = newValue; 1751 } 1752 1753 1758 public boolean getAppendCustomWhereClause() { 1759 return appendCustomWhereClause; 1760 } 1761 1764 1775 public synchronized void setDBName(String newOther) 1776 throws DBException { 1777 dbName = newOther; 1778 } 1779 1780 1781 1787 public void setSelectDistinct(boolean flag) { 1788 selectDistinct = flag; 1789 } 1790 1791 1797 public void setFieldsToRetrieve(String shortName, String fieldNames) throws DBException { 1798 DBObject oneObj = (DBObject) myDBObjects.get(shortName); 1799 1800 if (oneObj == null) { 1801 String myName = thisClass + "setFieldsToRetrieve(String, String)"; 1802 throw new DBException(myName + ":No such object as '" + shortName + 1803 "'"); 1804 } 1805 1806 oneObj.setFieldsToRetrieve(fieldNames); 1807 } 1808 1809 1816 public void setFieldsToRetrieveToNone(String shortName) throws DBException { 1817 DBObject oneObj = (DBObject) myDBObjects.get(shortName); 1818 1819 if (oneObj == null) { 1820 String myName = thisClass + "setFieldsToRetrieveToNone(String)"; 1821 throw new DBException(myName + ":No such object as '" + shortName + 1822 "'"); 1823 } 1824 1825 oneObj.retrieveFields = null; 1826 oneObj.anyFieldsToRetrieveMulti = true; 1827 } 1828 1829 1836 public void setFieldDistinct(String shortName, String fieldName, boolean flag) throws DBException { 1837 DBObject oneObj = (DBObject) myDBObjects.get(shortName); 1838 1839 if (oneObj == null) { 1840 String myName = thisClass + "setFieldDistinct(String, String, boolean)"; 1841 throw new DBException(myName + ":No such object as '" + shortName + 1842 "'"); 1843 } 1844 1845 oneObj.setFieldDistinct(fieldName, flag); 1846 } 1847 1848 1857 public void setField(String shortName, String fieldName, String fieldValue) 1858 throws DBException { 1859 DBObject oneObj = (DBObject) myDBObjects.get(shortName); 1860 1861 if (oneObj == null) { 1862 String myName = thisClass + "setField(String, String, String)"; 1863 throw new DBException(myName + ":No such object as '" + shortName + 1864 "'"); 1865 } 1866 1867 oneObj.setField(fieldName, fieldValue); 1868 } 1869 1870 1871 1881 public void setForeignKey(String shortName, String foreignKey, 1882 String shortName2, String primaryKey) 1883 throws DBException { 1884 String myName = thisClass + 1885 "setForeignKey(String, String, String, String)"; 1886 DBObject foreignDBObj = (DBObject) myDBObjects.get(shortName); 1887 1888 if (foreignDBObj == null) { 1889 throw new DBException(myName + ":DB Object with short name '" + 1890 shortName + "' is not part of this query"); 1891 } 1892 1893 DBObject primaryDBObj = (DBObject) myDBObjects.get(shortName2); 1894 1895 if (primaryDBObj == null) { 1896 throw new DBException(myName + ":DB Object with short name '" + 1897 shortName2 + "' is not part of this query"); 1898 } 1899 1900 relations.addElement(getTableName(foreignDBObj) + "." + foreignKey + 1901 " = " + getTableName(primaryDBObj) + "." + 1902 primaryKey); 1903 originalRelations.addElement(shortName + "|" + foreignKey + "|" + 1904 shortName2 + "|" + primaryKey); 1905 } 1906 1907 1915 public void setInnerJoin(String leftShortName, String leftColumn, 1916 String rightShortName, String rightColumn) 1917 throws DBException { 1918 1919 1924 originalJoins.addElement(leftShortName + "|" + leftColumn + "|" + 1925 rightShortName + "|" + rightColumn + "|inner"); 1926 } 1929 1930 1938 public void setLeftJoin(String leftShortName, String leftColumn, 1939 String rightShortName, String rightColumn) 1940 throws DBException { 1941 1942 1947 originalJoins.addElement(leftShortName + "|" + leftColumn + "|" + 1948 rightShortName + "|" + rightColumn + "|left"); 1949 } 1952 1953 1961 public void setRightJoin(String leftShortName, String leftColumn, 1962 String rightShortName, String rightColumn) 1963 throws DBException { 1964 1965 1970 originalJoins.addElement(leftShortName + "|" + leftColumn + "|" + 1971 rightShortName + "|" + rightColumn + "|right"); 1972 } 1975 1976 1985 private void buildJoin(String leftShortName, String leftColumn, 1986 String rightShortName, String rightColumn, 1987 int joinType) 1988 throws DBException { 1989 1990 2001 String onClause = ""; 2002 FastStringBuffer s = new FastStringBuffer(2048); 2003 FastStringBuffer fsb = new FastStringBuffer(256); 2004 2005 try { 2006 DBObject leftDBObj = getByShortName(leftShortName); 2007 DBObject rightDBObj = getByShortName(rightShortName); 2008 2009 if (fromClause == null) { 2010 s.append(getTableName(leftDBObj)); 2011 } else { 2012 s.append(fromClause); 2013 } 2014 2015 switch (joinType) { 2016 case INNER_JOIN: 2017 s.append(" INNER JOIN "); 2018 onClause = ""; 2020 break; 2021 case RIGHT_JOIN: 2022 s.append(" RIGHT JOIN "); 2023 onClause = buildWhereClauseBuffer(true, fsb, leftShortName); 2024 ignoreInWhereClause = 2025 ignoreInWhereClause + "," + leftShortName + ","; 2026 break; 2027 case LEFT_JOIN: 2028 s.append(" LEFT JOIN "); 2029 onClause = buildWhereClauseBuffer(true, fsb, rightShortName); 2030 ignoreInWhereClause = 2031 ignoreInWhereClause + "," + rightShortName + ","; 2032 break; 2033 } 2034 2035 if (onClause.length() > 5) { 2036 onClause = " AND " + onClause.substring(6); 2037 } 2038 2039 s.append(getTableName(rightDBObj) + 2040 " ON (" + getTableName(leftDBObj) + "." + 2041 leftColumn + " = " + getTableName(rightDBObj) + 2042 "." + rightColumn + onClause + ")"); 2043 2044 fromClause = s.toString(); 2045 } finally { 2046 s.release(); 2047 fsb.release(); 2048 } 2049 } 2052 2053 2062 public synchronized void setMaxRecords(int newMax) 2063 throws DBException { 2064 2065 if (maxRecords < 0) { 2066 String myName = (thisClass + "setMaxRecords(int)"); 2067 throw new DBException(myName + 2068 ":Max records can't be less than 0"); 2069 } 2070 2071 maxRecords = newMax; 2072 } 2073 2074 2075 2084 protected void setupFields() 2085 throws DBException { 2086 } 2087 2088 2089 2097 public String selectFieldString(DBObject oneObj, String fieldName) 2098 throws DBException { 2099 return StringUtil.replaceStringOnce(oneObj.selectFieldString(fieldName), 2100 fieldName, getTableName(oneObj) + "." + fieldName); 2101 2102 } 2103 2104 2112 public synchronized List makeDirectQueryList(String sqlQuery, int fieldCount) throws DBException { 2113 2114 DBConnectionPool myPool = null; 2115 DBConnection myConnection = null; 2116 2117 try { 2118 if (localConnection != null) { 2119 myConnection = localConnection; 2120 } else { 2121 myPool = DBConnectionPool.getInstance(getDBName()); 2122 myConnection = myPool.getConnection("com.jcorporate.expresso.core.dbobj.DBObject"); 2123 } 2124 2125 if (recordSet == null) { 2126 String myName = (thisClass + "makeDirectQueryList()"); 2127 throw new DBException(myName + 2128 ":Database object not correctly initialized"); 2129 } 2130 2131 recordSet.clear(); 2132 2133 if (log.isDebugEnabled()) { 2134 log.debug("Executing " + sqlQuery); 2135 } 2136 2137 if (fieldCount > 0) { 2138 myConnection.execute(sqlQuery); 2139 } else { 2140 myConnection.executeUpdate(sqlQuery); 2141 } 2142 2143 int recordCount = 0; 2144 while (fieldCount > 0 && myConnection.next()) { 2145 recordCount++; 2146 2147 if ((recordCount > maxRecords) && (maxRecords > 0)) { 2148 break; 2149 } 2150 2151 List tFieldValues = new ArrayList (); 2153 for (int i = 1; i <= fieldCount; i++) { 2154 String oneFieldValue = null; 2155 2156 try { 2157 oneFieldValue = myConnection.getString(i); 2158 } catch (DBException de) { 2159 throw new DBException(thisClass + "makeDirectQueryList()" + ":Error retrieving field " + i, de); 2160 } 2161 2162 tFieldValues.add(oneFieldValue); 2163 } 2164 2165 recordSet.add(tFieldValues); 2167 } 2168 2169 2170 } finally { 2171 if (localConnection == null) { 2172 myPool.release(myConnection); 2173 } 2174 } 2175 2176 return recordSet; 2177 } 2178 2179 2188 public DBObject assembleObject(String shortName) throws DBException { 2189 DBObject result = null; 2190 DBObject model = getDBObject(shortName); 2191 result = model.newInstance(); 2192 for (Iterator iterator = model.getMetaData().getAllFieldsMap().values().iterator(); iterator.hasNext();) { 2193 DBField oneField = (DBField) iterator.next(); 2194 try { 2195 if (oneField.isVirtual) { 2196 continue; } 2198 2199 String fieldName = oneField.getName(); 2200 if (isFieldNull(shortName, fieldName)) { 2201 result.setField(fieldName, (String ) null); 2202 } else { 2203 result.setField(fieldName, getField(shortName, fieldName)); 2204 } 2205 } catch (DBException e) { 2206 } 2208 } 2209 result.setStatus(DBObject.STATUS_CURRENT); 2210 return result; 2211 } 2212 2213 2219 public void setShortNameAsAlias(boolean flag) { 2220 shortNameAsAlias = flag; 2221 } 2222 2223 2224 2230 public boolean getShortNameAsAlias() { 2231 return shortNameAsAlias; 2232 } 2233 2234 2235 2242 private String getTableName(DBObject oneObj) 2243 throws DataException { 2244 String name = (String ) oneObj.getAttribute(SHORT_NAME); 2245 if (name != null && shortNameAsAlias) { 2246 return name; 2247 } 2248 return oneObj.getJDBCMetaData().getTargetSQLTable(oneObj.getDataContext()); 2249 } 2250 2251 2254 public DBConnection getConnection() { 2255 return localConnection; 2256 } 2257 2258 2261 public void setConnection(DBConnection connection) { 2262 localConnection = connection; 2263 } 2264 2265 2268 public boolean isFieldNull(String shortName, String fieldName) 2269 throws DBException { 2270 return getByShortName(shortName).isFieldNull(fieldName); 2271 } 2272 2273} 2274 | Popular Tags |