1 64 package com.jcorporate.expresso.core.dataobjects.jdbc; 65 66 import EDU.oswego.cs.dl.util.concurrent.ConcurrentReaderHashMap; 67 import com.jcorporate.expresso.core.ExpressoSchema; 68 import com.jcorporate.expresso.core.dataobjects.BaseDataObject; 69 import com.jcorporate.expresso.core.dataobjects.DataException; 70 import com.jcorporate.expresso.core.dataobjects.DataExecutorInterface; 71 import com.jcorporate.expresso.core.dataobjects.DataField; 72 import com.jcorporate.expresso.core.dataobjects.DataFieldMetaData; 73 import com.jcorporate.expresso.core.dataobjects.DataObject; 74 import com.jcorporate.expresso.core.dataobjects.DataObjectFactory; 75 import com.jcorporate.expresso.core.dataobjects.DataObjectMetaData; 76 import com.jcorporate.expresso.core.dataobjects.DataQueryInterface; 77 import com.jcorporate.expresso.core.dataobjects.Defineable; 78 import com.jcorporate.expresso.core.dataobjects.NestableDataObject; 79 import com.jcorporate.expresso.core.dataobjects.Securable; 80 import com.jcorporate.expresso.core.db.DBConnection; 81 import com.jcorporate.expresso.core.db.DBConnectionPool; 82 import com.jcorporate.expresso.core.db.DBException; 83 import com.jcorporate.expresso.core.dbobj.RequestContext; 84 import com.jcorporate.expresso.core.dbobj.SecuredDBObject; 85 import com.jcorporate.expresso.core.misc.StringUtil; 86 import com.jcorporate.expresso.core.registry.RequestRegistry; 87 import com.jcorporate.expresso.core.security.User; 88 import com.jcorporate.expresso.core.security.filters.Filter; 89 import com.jcorporate.expresso.kernel.util.ClassLocator; 90 import com.jcorporate.expresso.kernel.util.FastStringBuffer; 91 import com.jcorporate.expresso.services.dbobj.Setup; 92 import org.apache.log4j.Logger; 93 import org.apache.oro.text.regex.Pattern; 94 95 import java.util.ArrayList ; 96 import java.util.HashMap ; 97 import java.util.Iterator ; 98 import java.util.List ; 99 import java.util.Locale ; 100 import java.util.Map ; 101 import java.util.Set ; 102 import java.util.StringTokenizer ; 103 import java.util.TreeSet ; 104 105 106 126 public class JoinedDataObject implements DataObject, Defineable, Securable 127 , NestableDataObject { 128 private static final transient String thisClass = JoinedDataObject.class. 129 getName() + 130 "."; 131 132 private static final Logger LOG = Logger.getLogger(JoinedDataObject.class); 133 134 public static final int UNSPECIFIED_JOIN = -1; 135 136 139 public static final int INNER_JOIN = 0; 140 141 144 public static final int RIGHT_JOIN = 1; 145 146 149 public static final int LEFT_JOIN = 2; 150 151 152 155 private static transient final Logger log = Logger.getLogger(JoinedDataObject.class); 156 157 161 protected transient DBConnection localConnection = null; 162 163 167 protected int offsetRecord = 0; 168 169 170 173 protected int maxRecords = 0; 174 175 178 private HashMap attributes = null; 179 180 184 private HashMap myDataObjects = new HashMap(); 185 186 187 191 private ArrayList recordSet = null; 192 193 194 197 private Locale myLocale = null; 198 199 203 private String customWhereClause = null; 204 205 210 private boolean appendCustomWhere = false; 211 212 218 private boolean caseSensitiveQuery = true; 219 220 221 225 private String thisDefinitionName = null; 226 227 228 231 transient private static Map definitions = new ConcurrentReaderHashMap(); 232 233 236 private int uid = Securable.SYSTEM_ACCOUNT; 237 238 241 transient static private final JDBCUtil sJdbcUtil = JDBCUtil.getInstance(); 242 243 244 249 private Map myFields = new HashMap(); 250 251 252 255 public JoinedDataObject() { 256 setDataContext(RequestRegistry.getDataContext()); 257 try { 258 setRequestingUid(RequestRegistry.getUser().getUid()); 259 } catch (DBException e) { 260 LOG.error(e); 261 } 262 } 263 264 269 public JoinedDataObject(RequestContext request) { 270 setDataContext(request.getDBName()); 271 setRequestingUid(request.getUid()); 272 } 273 274 281 public JoinedDataObject(String xmlFileURL) throws DataException { 282 thisDefinitionName = xmlFileURL; 283 init(); 284 } 285 286 293 public JoinedDataObject(JoinedDataObject definition) throws DataException { 294 this.setDefinitionName(definition.getDefinitionName()); 295 this.setDataContext(definition.getDataContext()); 296 } 297 298 311 public JoinedDataObject(JoinedDigesterBean definition, 312 String definitionName) throws DataException { 313 thisDefinitionName = definitionName; 314 initWithBean(definition, definitionName); 315 } 316 317 322 public String getDefinitionName() { 323 return thisDefinitionName; 324 } 325 326 331 protected synchronized void init() throws DataException { 332 if (log.isDebugEnabled()) { 333 log.debug("Initializing new JoinedDataObject"); 334 } 335 synchronized (JoinedDataObject.class) { 336 try { 337 if (this.getMetaData() == null) { 338 JoinedDataObjectMetaData metadata = constructMetadata(); 339 definitions.put(getDefinitionName(), metadata); 340 initializeXML(metadata); 341 } 342 343 myDataObjects = ((JoinedDataObjectMetaData) this 344 .getMetaData()).createNestedDataObjects(); 345 } catch (Throwable t) { 346 if (definitions.containsKey(getDefinitionName())) { 347 definitions.remove(getDefinitionName()); 348 } 349 log.error("Error initializing data object", t); 350 throw new DataException("Error initializing joined data object" 351 , t); 352 } 353 } 354 } 355 356 357 363 protected JoinedDataObjectMetaData constructMetadata() { 364 return new JoinedDataObjectMetaData(); 365 } 366 367 375 protected synchronized void initWithBean(JoinedDigesterBean digesterBean 376 , String definitionName) throws 377 DataException { 378 if (log.isDebugEnabled()) { 379 log.debug("Initializing new JoinedDataObject"); 380 } 381 synchronized (JoinedDataObject.class) { 382 try { 383 if (getMetaData() == null) { 384 JoinedDataObjectMetaData metadata = constructMetadata(); 385 definitions.put(definitionName, metadata); 386 initializeFromJoinedDigesterBean(digesterBean, metadata); 387 } 388 389 this.myDataObjects = ((JoinedDataObjectMetaData) this 390 .getMetaData()).createNestedDataObjects(); 391 } catch (Throwable t) { 392 if (definitions.containsKey(this.getDefinitionName())) { 393 definitions.remove(this.getDefinitionName()); 394 } 395 log.error("Error initializing data object", t); 396 throw new DataException("Error initializing joined data object" 397 , t); 398 } 399 } 400 401 } 402 403 411 protected void initializeFromJoinedDigesterBean(JoinedDigesterBean 412 digesterBean, 413 JoinedDataObjectMetaData metadata) throws DataException { 414 metadata.setSelectDistinct(digesterBean.isDistinct()); 415 metadata.setDescription(digesterBean.getDescription()); 416 417 List l = digesterBean.getDataObjects(); 418 for (Iterator i = l.iterator(); i.hasNext();) { 419 JoinedDigesterBean.DigesterJoinedDataObject oneObj = 420 (JoinedDigesterBean.DigesterJoinedDataObject) i.next(); 421 try { 422 Class c = ClassLocator.loadClass(oneObj.getClassName()); 423 metadata.addDataObject(c, oneObj.getDefinitionName() 424 , oneObj.getAlias(), 425 oneObj.getFieldExpressionList()); 426 } catch (ClassNotFoundException ex) { 427 throw new DataException("Error parsing definition: unable to locate class: " 428 + oneObj.getClassName()); 429 } 430 } 431 432 metadata.setPermissions(digesterBean.getPermissions()); 433 434 List r = digesterBean.getRelations(); 435 for (Iterator i = r.iterator(); i.hasNext();) { 436 JoinedDigesterBean.DigesterJoinRelations oneRelation = 437 (JoinedDigesterBean.DigesterJoinRelations) i.next(); 438 439 try { 440 String joinType = oneRelation.getJoinType(); 441 int joinValue = UNSPECIFIED_JOIN; 442 443 if ("inner".equalsIgnoreCase(joinType)) { 444 joinValue = INNER_JOIN; 445 446 } else if ("left".equalsIgnoreCase(joinType)) { 447 joinValue = LEFT_JOIN; 448 449 } else if ("right".equalsIgnoreCase(joinType)) { 450 joinValue = RIGHT_JOIN; 451 } 452 453 metadata.setForeignKey(oneRelation.getLocalAlias(), 454 oneRelation.getLocalKey(), 455 oneRelation.getForeignAlias(), 456 oneRelation.getForeignKey(), joinValue); 457 } catch (DBException ex) { 458 throw new DataException("Error setting keys for join", ex); 459 } 460 } 461 462 } 463 464 469 protected void initializeXML(JoinedDataObjectMetaData metadata) throws 470 DataException { 471 if (log.isDebugEnabled()) { 472 log.debug("Initializing XML metadata for: " 473 + this.getDefinitionName()); 474 } 475 476 String fileLocation = this.getDefinitionName(); 477 java.net.URL def = this.getClass().getResource(fileLocation); 478 if (def == null) { 479 throw new DataException("Unable to load metadata at: " 480 + fileLocation); 481 } 482 483 JoinedDigesterBean digesterBean = new JoinedDigesterBean(); 484 digesterBean.loadJoinData(def); 485 initializeFromJoinedDigesterBean(digesterBean, metadata); 486 } 487 488 493 public Map getAllAttributes() { 494 return attributes; 495 } 496 497 504 public void setAttribute(String attributeName, Object attributeValue) { 505 if (attributes == null) { 506 attributes = new HashMap(); 507 } 508 509 attributes.put(attributeName, attributeValue); 510 } 511 512 518 public Object getAttribute(String attributeName) { 519 if (attributes != null) { 520 return attributes.get(attributeName); 521 } else { 522 return null; 523 } 524 } 525 526 537 public void setCaseSensitiveQuery(boolean isCaseSensitiveQuery) { 538 caseSensitiveQuery = isCaseSensitiveQuery; 539 } 540 541 548 public synchronized void setCustomWhereClause(String customWhereClause 549 , boolean append) { 550 this.customWhereClause = customWhereClause; 551 this.appendCustomWhere = append; 552 553 } 554 555 561 public void setDataContext(String newContext) { 562 for (Iterator i = myDataObjects.keySet().iterator(); i.hasNext();) { 563 String key = (String ) i.next(); 564 565 DataObject oneobj = (DataObject) myDataObjects.get(key); 566 oneobj.setDataContext(newContext); 567 } 568 } 569 570 575 public String getDataContext() { 576 Iterator i = myDataObjects.values().iterator(); 577 if (i.hasNext()) { 578 DataObject oneobj = (DataObject) i.next(); 579 return oneobj.getDataContext(); 580 } else { 581 return "default"; 582 } 583 } 584 585 593 public void setDataField(String fieldName, DataField o) throws 594 DataException { 595 596 DataField field = (DataField) this.myFields.get(fieldName); 597 598 if (field != null && !(o instanceof JoinedDataField)) { 599 throw new IllegalStateException ("Can't be setting a joined data field with a non-joined data field"); 600 } 601 602 if (field != null) { 603 this.myFields.put(fieldName, o); 604 } else { 605 JoinedDataObjectMetaData metadata = this.getJoinMetaData(); 606 String [] location = metadata.getObjectAndField(fieldName); 607 DataObject localObject = (DataObject) this.myDataObjects.get(location[0]); 608 localObject.set(location[1], o); 609 } 610 } 611 612 620 public DataField getDataField(String fieldName) throws DBException { 621 622 DataField field = (DataField) this.myFields.get(fieldName); 626 if (field != null) { 627 return field; 628 } 629 630 JoinedDataObjectMetaData metadata = this.getJoinMetaData(); 631 String rightKey = (String ) metadata.foreignKeyToPrimaryKeyMap.get(fieldName); 632 String leftKey = (String ) metadata.primaryToForeignKeyMap.get(fieldName); 633 String location[] = metadata.getObjectAndField(fieldName); 634 DataObject oneObj = (DataObject) myDataObjects.get(location[0]); 635 JoinedDataField joinField = null; 636 637 if ((rightKey == null || rightKey.length() == 0) 638 && (leftKey == null || leftKey.length() == 0)) { 639 field = oneObj.getDataField(location[1]); 640 if (field.getFieldMetaData().isVirtual()) { 641 field.setValue(oneObj.getField(location[1])); 642 } 643 return field; 644 } else if ((rightKey != null && rightKey.length() > 0) 645 && (leftKey == null || leftKey.length() == 0)) { 646 String rightLocation[] = metadata.getObjectAndField(rightKey); 648 649 joinField = (JoinedDataField) this.myFields.get(fieldName); 650 if (joinField == null) { 651 joinField = JoinedDataField.getInstance(this 652 , (DataObject) this.myDataObjects.get(location[0]) 653 , location[1], 654 (DataObject) this.myDataObjects.get(rightLocation[0]) 655 , rightLocation[1]); 656 } 657 658 this.myFields.put(fieldName, joinField); 663 this.myFields.put(rightKey, joinField); 664 665 } else { 666 String leftLocation[] = metadata.getObjectAndField(leftKey); 668 joinField = (JoinedDataField) this.myFields.get(leftKey); 669 if (joinField == null) { 670 joinField = JoinedDataField.getInstance(this 671 , (DataObject) this.myDataObjects.get(leftLocation[0]) 672 , leftLocation[1], 673 (DataObject) this.myDataObjects.get(location[0]), location[1]); 674 } 675 676 this.myFields.put(fieldName, joinField); 681 this.myFields.put(leftKey, joinField); 682 683 } 684 685 return joinField; 686 } 687 688 689 696 public DataExecutorInterface getExecutor() { 697 Iterator i = myDataObjects.values().iterator(); 698 if (i.hasNext()) { 699 DataObject oneobj = (DataObject) i.next(); 700 return oneobj.getExecutor(); 701 } else { 702 return null; 703 } 704 } 705 706 707 713 public DataFieldMetaData getFieldMetaData(String fieldName) { 714 StringTokenizer stok = new StringTokenizer (StringUtil.notNull(fieldName) 715 , "."); 716 if (!stok.hasMoreTokens()) { 717 throw new IllegalArgumentException ("Field name must be proper format"); 718 } 719 720 JDBCDataObject dataobject = (JDBCDataObject) this.myDataObjects.get(stok. 721 nextToken()); 722 if (!stok.hasMoreTokens()) { 723 throw new IllegalArgumentException ("Field name must be proper format"); 724 } 725 726 if (dataobject == null) { 727 throw new IllegalArgumentException ("Unable to find specified data object in this Join"); 728 } 729 730 return dataobject.getFieldMetaData(stok.nextToken()); 731 } 732 733 740 public void set(String fieldName, Object o) throws DataException { 741 742 try { 743 this.getDataField(fieldName).setValue(o); 744 } catch (DBException ex) { 745 throw new DataException("Unable to set field value for field " 746 + fieldName + " value " + o.toString()); 747 } 748 } 749 750 757 public Object get(String fieldName) throws DataException { 758 try { 759 return this.getDataField(fieldName).getValue(); 760 } catch (DBException ex) { 761 throw new DataException("Error retrieving data field", ex); 762 } 763 } 764 765 766 771 public String getKey() { 772 JoinedDataObjectMetaData metadata = (JoinedDataObjectMetaData) this. 773 getMetaData(); 774 775 String alias = metadata.getPrimaryAlias(); 776 JDBCDataObject primaryObject = null; 777 try { 778 primaryObject = this.getByShortName(alias); 779 return primaryObject.getKey(); 780 } catch (DataException ex) { 781 log.error("Error dataobject by name: " + alias, ex); 782 return ""; 783 } 784 } 785 786 787 792 public void setLocale(Locale newLocale) { 793 myLocale = newLocale; 794 } 795 796 801 public Locale getLocale() { 802 if (myLocale == null) { 803 myLocale = Locale.getDefault(); 804 } 805 806 return myLocale; 807 } 808 809 814 public String getMappedDataContext() { 815 JoinedDataObjectMetaData metadata = (JoinedDataObjectMetaData) this. 816 getMetaData(); 817 818 String alias = metadata.getPrimaryAlias(); 819 JDBCDataObject primaryObject = null; 820 try { 821 primaryObject = this.getByShortName(alias); 822 return primaryObject.getMappedDataContext(); 823 } catch (DataException ex) { 824 log.error("Error dataobject by name: " + alias, ex); 825 return ""; 826 } 827 } 828 829 834 public void setMaxRecords(int newMax) throws DBException { 835 maxRecords = newMax; 836 } 837 838 843 public int getMaxRecords() { 844 return maxRecords; 845 } 846 847 857 public DataObjectMetaData getMetaData() { 858 return (DataObjectMetaData) definitions.get(this.getDefinitionName()); 859 } 860 861 866 public JoinedDataObjectMetaData getJoinMetaData() { 867 return (JoinedDataObjectMetaData) getMetaData(); 868 } 869 870 871 882 public ArrayList getDataObjects() { 883 ArrayList al = new ArrayList (this.myDataObjects.size()); 884 JoinedDataObjectMetaData metadata = this.getJoinMetaData(); 885 for (Iterator i = metadata.getAliasesInOrder().iterator(); i.hasNext();) { 886 String oneAlias = (String ) i.next(); 887 al.add(this.myDataObjects.get(oneAlias)); 888 } 889 890 return al; 891 } 892 893 905 public void setOffsetRecord(int newOffset) throws DBException { 906 if (newOffset < 0) { 907 throw new DBException("Offset records can't be less than 0"); 908 } 909 910 offsetRecord = newOffset; 911 } 912 913 914 915 924 public int getOffsetRecord() { 925 return offsetRecord; 926 } 927 928 929 930 935 public DataQueryInterface getQueryInterface() { 936 throw new java.lang.UnsupportedOperationException ("Method getQueryInterface() not yet implemented."); 937 } 938 939 945 public String getStatus() { 946 JoinedDataObjectMetaData metadata = (JoinedDataObjectMetaData) this. 947 getMetaData(); 948 949 String alias = metadata.getPrimaryAlias(); 950 JDBCDataObject primaryObject = null; 951 try { 952 primaryObject = this.getByShortName(alias); 953 return primaryObject.getStatus(); 954 } catch (DataException ex) { 955 log.error("Error dataobject by name: " + alias, ex); 956 return ""; 957 } 958 } 959 960 965 public void setStatus(String newValue) { 966 JoinedDataObjectMetaData metadata = (JoinedDataObjectMetaData) this. 967 getMetaData(); 968 969 String alias = metadata.getPrimaryAlias(); 970 JDBCDataObject primaryObject = null; 971 try { 972 primaryObject = this.getByShortName(alias); 973 primaryObject.setStatus(newValue); 974 } catch (DataException ex) { 975 log.error("Error dataobject by name: " + alias, ex); 976 } 977 978 } 979 980 981 989 public List getValidValuesList(String fieldName) throws DBException { 990 991 JoinedDataObjectMetaData metadata = this.getJoinMetaData(); 992 String location[] = metadata.getObjectAndField(fieldName); 993 994 DataObject dataobject = (DataObject) this.myDataObjects.get(location[0]); 995 return dataobject.getValidValuesList(location[1]); 996 } 997 998 1004 public void add() throws DBException { 1005 checkInitialized(); 1006 isAllowed(SecuredDBObject.ADD); 1007 1008 DBConnection connection = null; 1009 boolean localConn = false; 1010 if (localConnection != null) { 1011 connection = localConnection; 1012 localConn = true; 1013 } else { 1014 DBConnectionPool myPool = DBConnectionPool.getInstance(this. 1015 getMappedDataContext()); 1016 connection = myPool.getConnection("Joined DataObject Add"); 1017 connection.setAutoCommit(false); 1018 } 1019 1020 JoinedDataObjectMetaData joinMetadata = this.getJoinMetaData(); 1021 try { 1022 String allAliases[] = (String []) joinMetadata.getAliasesInOrder() 1023 .toArray(new String [myDataObjects.size()]); 1024 1025 for (int i = (allAliases.length - 1); i >= 0; i--) { 1028 String oneAlias = allAliases[i]; 1029 JDBCDataObject oneObject = (JDBCDataObject) this.myDataObjects. 1030 get(oneAlias); 1031 oneObject.setConnection(connection, this.getDataContext()); 1032 if (!oneObject.find()) { 1033 oneObject.add(); 1034 } else { 1035 oneObject.update(); 1039 continue; 1040 } 1041 1042 JDBCObjectMetaData metadata = oneObject.getJDBCMetaData(); 1043 for (Iterator j = metadata 1044 .getKeyFieldListArray().iterator(); j.hasNext();) { 1045 String oneFieldName = (String ) j.next(); 1046 1047 if (metadata.getFieldMetadata(oneFieldName). 1052 isAutoIncremented()) { 1053 String rightFieldName = allAliases[i] + "." 1054 + oneFieldName; 1055 String leftFieldName = (String ) joinMetadata. 1056 primaryToForeignKeyMap.get(rightFieldName); 1057 if (leftFieldName != null && leftFieldName.length() > 0) { 1058 String location[] = joinMetadata.getObjectAndField(leftFieldName); 1059 JDBCDataObject leftObject = (JDBCDataObject) this. 1060 myDataObjects.get(location[0]); 1061 leftObject.set(location[1], 1062 oneObject.get(oneFieldName)); 1063 } 1064 } 1065 1066 } 1067 1068 } 1069 if (!localConn) { 1070 connection.commit(); 1071 connection.release(); 1072 } 1073 } catch (DBException ex) { 1077 log.error("Error adding JoinedDataObject", ex); 1078 if (!localConn) { 1080 connection.rollback(); 1081 connection.release(); 1082 } else { 1083 throw ex; 1084 } 1085 } finally { 1086 } 1090 1091 setStatus(BaseDataObject.STATUS_CURRENT); 1092 } 1093 1094 1095 1103 public void checkField(String fieldName, String fieldValue) throws 1104 DBException { 1105 checkInitialized(); 1106 1107 String location[] = this.getJoinMetaData().getObjectAndField(fieldName); 1108 1109 DataObject oneObj = (DataObject) myDataObjects.get(location[0]); 1110 1111 oneObj.checkField(location[1], fieldValue); 1112 } 1113 1114 1115 1122 public boolean checkAllowed(String requestedFunction) throws DBException { 1123 try { 1124 isAllowed(requestedFunction); 1125 } catch (SecurityException de) { 1126 log.debug(de); 1127 return false; 1128 } 1129 1130 return true; 1131 } 1132 1133 1134 1137 public void clear() throws DBException { 1138 checkInitialized(); 1139 1140 for (Iterator i = this.myDataObjects.values().iterator(); i.hasNext();) { 1141 JDBCDataObject oneObj = (JDBCDataObject) i.next(); 1142 oneObj.clear(); 1143 } 1144 } 1145 1146 1153 protected String getDistinct(DBConnectionPool contextPool) { 1154 if (this.getJoinMetaData().isSelectDistinct()) { 1155 return " " + contextPool.getDistinctRowsetKeyword() + " "; 1156 } else { 1157 return ""; 1158 } 1159 } 1160 1161 1169 public int count() throws DBException { 1170 checkInitialized(); 1171 isAllowed(SecuredDBObject.SEARCH); 1172 1173 DBConnectionPool myPool = DBConnectionPool.getInstance(this. 1174 getMappedDataContext()); 1175 ; 1176 DBConnection myConnection = null; 1177 1178 JDBCDataObject primaryObject = (JDBCDataObject) this.getJoinMetaData(). 1179 getDataObjectsInOrder().get(0); 1180 ArrayList keyFields = primaryObject.getMetaData().getKeyFieldListArray(); 1181 1182 FastStringBuffer myStatement = FastStringBuffer.getInstance(); 1187 try { 1188 if (keyFields.size() > 1) { 1189 myStatement.append("SELECT "); 1190 myStatement.append(getDistinct(myPool)); 1191 myStatement.append(" COUNT(*) FROM "); 1192 } else { 1193 DataFieldMetaData keymetadata = primaryObject 1194 .getFieldMetaData((String ) 1195 keyFields.get(0)); 1196 myStatement.append("SELECT "); 1197 myStatement.append(getDistinct(myPool)); 1198 myStatement.append("COUNT( " 1199 + primaryObject.getJDBCMetaData(). 1200 getTargetSQLTable(primaryObject. 1201 getDataContext()) + "." 1202 + keymetadata.getName() + ") FROM "); 1203 } 1204 1205 myStatement.append(this.buildFromClause()); 1206 1207 if (customWhereClause != null) { 1208 if (appendCustomWhere) { 1209 buildWhereClauseBuffer(true, myStatement); 1210 formatCustomWhereClause(myStatement); 1211 } else { 1212 formatCustomWhereClause(myStatement); 1213 } 1214 } else { 1215 buildWhereClauseBuffer(true, myStatement); 1216 } 1217 1218 if (localConnection != null) { 1219 myConnection = localConnection; 1220 } else { 1221 1222 myConnection = myPool.getConnection(this.getDefinitionName()); 1223 } 1224 1225 myConnection.execute(myStatement.toString()); 1226 1227 if (myConnection.next()) { 1228 return myConnection.getInt(1); 1229 } else { 1230 log.warn("count() result set didn't return any values"); 1231 } 1232 } catch (DBException de) { 1233 log.error("Error performing count.", de); 1234 throw de; 1235 } catch (Exception e) { 1236 log.error("Error performing count.", e); 1237 throw new DataException("Exception performing count", e); 1238 } finally { 1239 myStatement.release(); 1240 if (localConnection == null && myConnection != null) { 1241 myConnection.release(); 1242 } 1243 } 1244 1245 return 0; 1246 } 1247 1248 1254 public void delete() throws DBException { 1255 checkInitialized(); 1256 isAllowed(SecuredDBObject.DELETE); 1257 DBConnectionPool myPool = null; 1258 DBConnection myConnection = null; 1259 1260 FastStringBuffer myStatement = FastStringBuffer.getInstance(); 1265 try { 1266 myStatement.append("DELETE FROM "); 1267 1268 myStatement.append(this.buildFromClause()); 1269 1270 if (customWhereClause != null) { 1271 if (appendCustomWhere) { 1272 buildWhereClauseBuffer(true, myStatement); 1273 formatCustomWhereClause(myStatement); 1274 } else { 1275 formatCustomWhereClause(myStatement); 1276 } 1277 } else { 1278 buildWhereClauseBuffer(true, myStatement); 1279 } 1280 1281 if (localConnection != null) { 1282 myConnection = localConnection; 1283 } else { 1284 myPool = DBConnectionPool.getInstance(this.getDataContext()); 1285 myConnection = myPool.getConnection(this.getDefinitionName()); 1286 } 1287 1288 myConnection.executeUpdate(myStatement.toString()); 1289 1290 } catch (DBException de) { 1291 log.error("Error performing count.", de); 1292 throw de; 1293 } catch (Exception e) { 1294 log.error("Error performing count.", e); 1295 throw new DataException("Exception performing count", e); 1296 } finally { 1297 myStatement.release(); 1298 if (localConnection == null && myConnection != null) { 1299 myConnection.release(); 1300 } 1301 } 1302 1303 setStatus(BaseDataObject.STATUS_DELETED); 1304 } 1305 1306 1312 public boolean equals(Object otherObject) { 1313 checkInitialized(); 1314 if (!(otherObject instanceof JoinedDataObject)) { 1315 return false; 1316 } 1317 1318 JoinedDataObject other = (JoinedDataObject) otherObject; 1319 1320 boolean returnValue = true; 1321 1322 for (Iterator i = myDataObjects.keySet().iterator(); i.hasNext();) { 1323 String oneObjName = (String ) i.next(); 1324 1325 if (!other.myDataObjects.containsKey(oneObjName)) { 1326 return false; 1327 } 1328 1329 DataObject myObj = (DataObject) myDataObjects.get(oneObjName); 1330 DataObject otherObj = (DataObject) other.myDataObjects.get(oneObjName); 1331 1332 returnValue &= myObj.equals(otherObj); 1333 1334 if (returnValue == false) { 1335 break; 1336 } 1337 } 1338 1339 return returnValue; 1340 } 1341 1342 1347 public int hashCode() { 1348 int returnValue = 0; 1349 for (Iterator i = myDataObjects.keySet().iterator(); i.hasNext();) { 1350 String oneObjName = (String ) i.next(); 1351 1352 DataObject myObj = (DataObject) myDataObjects.get(oneObjName); 1353 1354 returnValue ^= myObj.hashCode(); 1355 } 1356 1357 return returnValue; 1358 } 1359 1360 1361 1368 public boolean find() throws DBException { 1369 checkInitialized(); 1370 isAllowed(SecuredDBObject.SEARCH); 1371 1372 JoinedDataObject test = new JoinedDataObject(this); 1373 test.setMaxRecords(1); 1374 test.clear(); 1375 test.setRequestingUid(this.getRequestingUid()); 1376 test.setDataContext(this.getDataContext()); 1377 1378 ArrayList fieldList = this.getMetaData().getFieldListArray(); 1379 for (Iterator i = fieldList.iterator(); i.hasNext();) { 1380 String fieldName = (String ) i.next(); 1381 test.set(fieldName, this.getDataField(fieldName).getValue()); 1382 } 1383 1384 ArrayList al = test.searchAndRetrieveList(null); 1389 if (al.size() == 0) { 1390 return false; 1391 } else { 1392 JoinedDataObject oneObj = (JoinedDataObject) al.get(0); 1393 for (Iterator i = fieldList.iterator(); 1394 i.hasNext();) { 1395 String fieldName = (String ) i.next(); 1396 this.set(fieldName, oneObj.get(fieldName)); 1397 } 1398 1399 } 1400 setStatus(BaseDataObject.STATUS_CURRENT); 1401 return true; 1402 } 1403 1404 1405 1417 public ArrayList searchAndRetrieveList(String sortOrder) throws DBException { 1418 boolean needComma = false; 1419 isAllowed(SecuredDBObject.SEARCH); 1420 1421 HashMap rtrvListByTable = new HashMap(); 1422 1423 DBConnectionPool myPool = DBConnectionPool.getInstance(getDataContext()); 1424 DBConnection myConnection = null; 1425 1426 try { 1427 if (localConnection != null) { 1428 myConnection = localConnection; 1429 } else { 1430 myConnection = myPool.getConnection("JoinedDataObject.searchAndRetrieveList()"); 1431 } 1432 recordSet = new ArrayList (); 1433 1434 String fieldName = null; 1435 FastStringBuffer myStatement = new FastStringBuffer(256); 1436 myStatement.append("SELECT "); 1437 1438 if (myConnection.getLimitationPosition() 1439 == DBConnection.LIMITATION_AFTER_SELECT && 1440 (offsetRecord > 0 || maxRecords > 0)) { 1441 1442 String limitStub = JDBCUtil.getInstance().makeLimitationStub(myConnection, this); 1444 1445 myStatement.append(" "); 1446 myStatement.append(limitStub); 1447 myStatement.append(" "); 1448 } 1449 1450 myStatement.append(this.getDistinct(myPool)); 1451 1452 Iterator eachObj = this.getJoinMetaData().getDataObjectsInOrder(). 1453 iterator(); 1454 Iterator eachAlias = this.getJoinMetaData().getAliasesInOrder(). 1455 iterator(); 1456 JDBCDataObject oneObj = null; 1457 String oneAlias; 1458 1459 while (eachObj.hasNext()) { 1460 oneObj = (JDBCDataObject) eachObj.next(); 1461 oneAlias = (String ) eachAlias.next(); 1462 JDBCObjectMetaData metadata = oneObj.getJDBCMetaData(); 1463 1464 ArrayList retrievedFieldList = (ArrayList ) rtrvListByTable.get( 1465 metadata.getTargetSQLTable(oneObj.getDataContext())); 1466 if (retrievedFieldList == null) { 1467 retrievedFieldList = new ArrayList (); 1468 rtrvListByTable.put(metadata.getTargetSQLTable(oneObj. 1469 getDataContext()), retrievedFieldList); 1470 } 1471 1472 List fieldsToRetrieve = this.getJoinMetaData(). 1473 getFieldsToRetrieve(oneAlias); 1474 if (fieldsToRetrieve != null) { 1475 if (fieldsToRetrieve.isEmpty()) { 1476 continue; 1478 } 1479 JoinedDataObjectMetaData.FieldList fieldList = null; 1480 for (Iterator i = fieldsToRetrieve.iterator(); i.hasNext();) { 1481 fieldList = (JoinedDataObjectMetaData.FieldList) i.next(); 1482 String fieldExpression = fieldList.getFieldExpression(); 1483 fieldName = fieldList.getFieldName(); 1484 boolean isExpression = fieldList.isExpression(); 1485 DataFieldMetaData metaData = 1486 oneObj.getFieldMetaData(fieldName); 1487 1488 if (!metaData.isVirtual() 1489 && !metaData.isBinaryObjectType()) { 1490 if (needComma) { 1491 myStatement.append(", "); 1492 } 1493 if (isExpression) { 1494 myStatement.append(fieldExpression); 1496 } else { 1497 myStatement.append(selectFieldString(oneObj 1498 , fieldName)); 1499 } 1500 retrievedFieldList.add(fieldName); 1501 needComma = true; 1502 } 1503 1504 } 1505 1506 } else { 1507 for (Iterator i = metadata.getFieldListArray().iterator(); 1508 i.hasNext(); 1509 ) { 1510 fieldName = (String ) i.next(); 1511 DataFieldMetaData metaData = 1512 oneObj.getFieldMetaData(fieldName); 1513 1514 if (!metaData.isVirtual() 1515 && !metaData.isBinaryObjectType()) { 1516 if (needComma) { 1517 myStatement.append(", "); 1518 } 1519 1520 myStatement.append(selectFieldString(oneObj 1521 , fieldName)); 1522 retrievedFieldList.add(fieldName); 1523 needComma = true; 1524 } 1525 1526 1527 } 1528 1529 1530 } 1531 } 1532 1533 myStatement.append(" FROM "); 1534 myStatement.append(this.buildFromClause()); 1535 1536 if (myConnection.getLimitationPosition() 1537 == DBConnection.LIMITATION_AFTER_TABLE && 1538 (offsetRecord > 0 || maxRecords > 0)) { 1539 1540 String limitStub = JDBCUtil.getInstance().makeLimitationStub(myConnection, this); 1542 myStatement.append(" "); 1543 myStatement.append(limitStub); 1544 myStatement.append(" "); 1545 } 1546 1547 if (customWhereClause != null) { 1548 if (appendCustomWhere) { 1549 buildWhereClauseBuffer(true, myStatement); 1550 formatCustomWhereClause(myStatement); 1551 } else { 1552 formatCustomWhereClause(myStatement); 1553 } 1554 } else { 1555 buildWhereClauseBuffer(true, myStatement); 1556 } 1557 1558 if (myConnection.getLimitationPosition() 1559 == DBConnection.LIMITATION_AFTER_WHERE && 1560 (offsetRecord > 0 || maxRecords > 0)) { 1561 1562 String limitStub = JDBCUtil.getInstance().makeLimitationStub(myConnection, this); 1564 1565 myStatement.append(" "); 1566 myStatement.append(limitStub); 1567 myStatement.append(" "); 1568 } 1569 1570 myStatement.append(this.buildOrderByString(sortOrder)); 1571 myConnection.execute(myStatement.toString()); 1572 1573 int recordCount = 0; 1574 int retrieveCount = 0; 1575 while (myConnection.next()) { 1576 recordCount++; 1577 retrieveCount++; 1578 1579 if (retrieveCount < offsetRecord && offsetRecord > 0 && 1582 myConnection.getLimitationPosition() 1583 == DBConnection.LIMITATION_DISABLED) { 1584 continue; 1585 } else if (retrieveCount == offsetRecord && offsetRecord > 0 && 1586 myConnection.getLimitationPosition() 1587 == DBConnection.LIMITATION_DISABLED) { 1588 recordCount = 0; continue; } 1591 if ((recordCount > maxRecords) && (maxRecords > 0)) { 1592 this.setAttribute("More Records", "Y"); 1593 break; 1594 } 1595 1596 JoinedDataObject myObj = new JoinedDataObject(this); 1597 int i = 1; 1598 1599 if (log.isDebugEnabled()) { 1600 log.debug("Retrieved row " + recordCount); 1601 } 1602 1603 String oneFieldValue = null; 1604 1605 eachAlias = this.getJoinMetaData().getAliasesInOrder().iterator(); 1607 1608 while (eachAlias.hasNext()) { 1609 oneAlias = (String ) eachAlias.next(); 1610 oneObj = (JDBCDataObject) myObj.myDataObjects.get(oneAlias); 1611 JDBCObjectMetaData objectMetadata = oneObj.getJDBCMetaData(); 1612 1613 ArrayList retrievedFieldList = (ArrayList ) rtrvListByTable. 1614 get(objectMetadata.getTargetSQLTable(oneObj. 1615 getDataContext())); 1616 1617 for (Iterator it = retrievedFieldList.iterator(); 1618 it.hasNext();) { 1619 fieldName = (String ) it.next(); 1620 DataFieldMetaData metaData = oneObj.getFieldMetaData(fieldName); 1621 1622 if (!metaData.isVirtual() 1623 && !metaData.isBinaryObjectType()) { 1624 try { 1625 oneFieldValue = myConnection.getString(i); 1626 } catch (DBException de) { 1627 String myName = (thisClass 1628 + "searchAndRetrieve()"); 1629 throw new DBException(myName + 1630 ":Error retrieving field '" + 1631 objectMetadata.getTargetSQLTable(oneObj. 1632 getDataContext()) + 1633 "." + fieldName + "'", 1634 de); 1635 } 1636 1637 i++; 1638 1639 if (log.isDebugEnabled()) { 1640 log.debug("Setting " + 1641 objectMetadata.getTargetTable() + "." + 1642 fieldName + " to " + oneFieldValue); 1643 } 1644 1645 myObj.set(oneAlias + "." + fieldName, oneFieldValue); 1646 } 1647 } 1648 } 1649 1650 1651 myObj.setDataContext(getDataContext()); 1652 1653 if (myObj instanceof Securable) { 1654 myObj.setRequestingUid(this.getRequestingUid()); 1655 } 1656 1657 myObj.setStatus(BaseDataObject.STATUS_CURRENT); 1658 recordSet.add(myObj); 1659 } 1660 1661 1662 } catch (Exception e) { 1663 log.error("Error finding join", e); 1664 throw new DBException("Error finding objects", e); 1665 } catch (Throwable t) { 1666 log.error("Error finding join", t); 1667 throw new DBException("Error finding objects", t); 1668 } finally { 1669 if (localConnection == null) { 1670 myPool.release(myConnection); 1671 } 1672 } 1673 1674 return recordSet; 1675 1676 } 1677 1678 1685 public ArrayList searchAndRetrieveList() throws DBException { 1686 return searchAndRetrieveList(null); 1687 } 1688 1689 1702 protected String selectFieldString(JDBCDataObject oneObj, String fieldName) throws 1703 DBException { 1704 checkInitialized(); 1705 return StringUtil.replaceStringOnce(oneObj.selectFieldString(fieldName), 1706 fieldName 1707 , oneObj.getJDBCMetaData(). 1708 getTargetSQLTable(oneObj. 1709 getDataContext()) + "." + fieldName); 1710 } 1711 1712 1713 1714 1720 public void update() throws DBException { 1721 checkInitialized(); 1722 isAllowed(SecuredDBObject.UPDATE); 1723 DBConnection connection = null; 1724 1725 boolean localConn = false; 1726 if (localConnection != null) { 1727 connection = localConnection; 1728 localConn = true; 1729 } else { 1730 DBConnectionPool myPool = DBConnectionPool.getInstance(this. 1731 getMappedDataContext()); 1732 1733 connection = myPool.getConnection("Joined DataObject Update"); 1734 connection.setAutoCommit(false); 1735 } 1736 1737 try { 1738 for (Iterator i = this.myDataObjects.values().iterator(); i.hasNext();) { 1739 JDBCDataObject oneObj = (JDBCDataObject) i.next(); 1740 oneObj.setConnection(connection, this.getDataContext()); 1741 this.addOrUpdate(oneObj); 1742 } 1743 if (!localConn) { 1745 connection.commit(); 1746 connection.release(); 1747 } 1748 1749 } catch (DBException ex) { 1750 log.error("Error executing SQL statement", ex); 1751 if (!localConn) { 1753 connection.rollback(); 1754 connection.release(); 1755 } else { 1756 throw ex; 1757 } 1758 } catch (Throwable t) { 1759 log.error("Error updating join", t); 1760 if (!localConn) { 1761 connection.rollback(); 1762 connection.release(); 1763 } 1764 throw new DataException("Error updating join", t); 1765 } finally { 1766 } 1771 1772 for (Iterator i = this.myDataObjects.values().iterator(); i.hasNext();) { 1775 JDBCDataObject oneObj = (JDBCDataObject) i.next(); 1776 oneObj.setConnection(null, this.getDataContext()); 1777 } 1778 1779 setStatus(BaseDataObject.STATUS_CURRENT); 1780 } 1781 1782 1788 public synchronized void addOrUpdate(JDBCDataObject testObject) throws 1789 DBException { 1790 JDBCDataObject searchObj = (JDBCDataObject) DataObjectFactory. 1791 createDataObject(testObject 1792 .getClass(), this.getDataContext(), this.getRequestingUid()); 1793 1794 searchObj.setDataContext(getDataContext()); 1795 String oneFieldName = null; 1796 1797 for (Iterator i = searchObj.getMetaData().getKeyFieldListArray(). 1798 iterator(); i.hasNext();) { 1799 oneFieldName = (String ) i.next(); 1800 searchObj.set(oneFieldName, testObject.getField(oneFieldName)); 1801 } 1802 1803 if (searchObj.find()) { 1804 1805 if (testObject.getMetaData().getKeyFieldListArray().size() 1808 == testObject.getMetaData().getFieldListArray().size()) { 1809 } else { 1812 testObject.getExecutor().update(testObject, true); 1813 } 1814 } else { 1815 testObject.add(); 1816 } 1817 } 1818 1819 1820 1827 private JDBCDataObject getByShortName(String shortName) throws 1828 DataException { 1829 StringUtil.assertNotBlank(shortName, "Short name may not be blank"); 1830 1831 JDBCDataObject oneObj = (JDBCDataObject) myDataObjects.get(shortName); 1832 1833 if (oneObj == null) { 1834 throw new DataException("No such object as '" + shortName + "'"); 1835 } 1836 1837 return oneObj; 1838 } 1839 1840 1841 1856 private String buildJoin(String leftShortName, String leftColumn, 1857 String rightShortName, String rightColumn 1858 , int joinType) throws DBException { 1859 checkInitialized(); 1860 JDBCDataObject leftDBObj = getByShortName(leftShortName); 1861 JDBCDataObject rightDBObj = getByShortName(rightShortName); 1862 1863 ArrayList leftCols = new ArrayList (3); 1864 ArrayList rightCols = new ArrayList (3); 1865 StringTokenizer stok = new StringTokenizer (leftColumn, "|"); 1866 while (stok.hasMoreTokens()) { 1867 leftCols.add(stok.nextToken()); 1868 } 1869 stok = new StringTokenizer (rightColumn, "|"); 1870 while (stok.hasMoreTokens()) { 1871 rightCols.add(stok.nextToken()); 1872 } 1873 FastStringBuffer buffer = FastStringBuffer.getInstance(); 1874 1875 try { 1876 1877 switch (joinType) { 1878 case INNER_JOIN: 1879 buffer.append(" INNER JOIN "); 1880 break; 1881 1882 case RIGHT_JOIN: 1883 buffer.append(" RIGHT JOIN "); 1884 break; 1885 1886 case LEFT_JOIN: 1887 buffer.append(" LEFT JOIN "); 1888 break; 1889 1890 case UNSPECIFIED_JOIN: 1891 throw new IllegalArgumentException ("BuildJoin does not support Unspecified joins"); 1892 1893 } 1894 1895 buffer.append(rightDBObj.getJDBCMetaData().getTargetSQLTable(rightDBObj.getDataContext())); 1896 buffer.append(" ON "); 1897 buffer.append(leftDBObj.getJDBCMetaData().getTargetSQLTable(leftDBObj.getDataContext())); 1898 buffer.append("."); 1899 buffer.append(leftColumn); 1900 buffer.append(" = "); 1901 buffer.append(rightDBObj.getJDBCMetaData().getTargetSQLTable(rightDBObj.getDataContext())); 1902 buffer.append("."); 1903 buffer.append(rightColumn); 1904 buffer.append(" "); 1905 boolean addAnd = false; 1906 1907 for (int i = 0; i < leftCols.size(); i++) { 1908 if (addAnd) { 1909 buffer.append(" AND "); 1910 } 1911 buffer.append(leftDBObj.getJDBCMetaData().getTargetTable()); 1912 buffer.append("."); 1913 buffer.append((String ) leftCols.get(i)); 1914 buffer.append(" = "); 1915 buffer.append(rightDBObj.getJDBCMetaData().getTargetTable()); 1916 buffer.append("."); 1917 buffer.append((String ) rightCols.get(i)); 1918 addAnd = true; 1919 } 1920 buffer.append(") "); 1921 1922 return buffer.toString(); 1923 } catch (DBException ex) { 1924 throw new DBException("Error building join string", ex); 1925 } finally { 1926 buffer.release(); 1927 } 1928 } 1929 1930 1931 1943 public void setDefinitionName(String definitionName) throws DataException { 1944 thisDefinitionName = definitionName; 1945 init(); 1946 } 1947 1948 1953 public int getRequestingUid() { 1954 return this.uid; 1955 } 1956 1957 1963 public void setRequestingUid(int newUid) { 1964 1965 this.uid = newUid; 1966 for (Iterator i = this.myDataObjects.keySet().iterator(); i.hasNext();) { 1967 1968 String key = (String ) i.next(); 1969 1970 DataObject value = (DataObject) myDataObjects.get(key); 1971 1972 if (value instanceof Securable) { 1973 ((Securable) value).setRequestingUid(newUid); 1974 } 1975 } 1976 } 1977 1978 1985 public void isAllowed(String requestedFunction) throws SecurityException , 1986 com.jcorporate.expresso.core.db.DBException { 1987 checkInitialized(); 1988 1989 if (getRequestingUid() == SecuredDBObject.SYSTEM_ACCOUNT 1990 || User.getUserFromId(getRequestingUid(), getDataContext()).isAdmin()) { 1991 return; 1993 } 1994 1995 Boolean override = (Boolean ) getJoinMetaData().getPermissions().get(requestedFunction); 1999 if (override != null && override.booleanValue() == false) { 2000 throw new SecurityException ("Method: " + requestedFunction 2001 + " not allowed"); 2002 } 2003 2004 for (Iterator i = this.myDataObjects.keySet().iterator(); i.hasNext();) { 2005 String key = (String ) i.next(); 2006 2007 DataObject value = (DataObject) myDataObjects.get(key); 2008 if (value instanceof Securable) { 2009 ((Securable) value).isAllowed(requestedFunction); 2010 } else { 2011 String insecureAllowed = Setup.getValue(getDataContext(), ExpressoSchema.class.getName(), 2012 "insecureDBMaint"); 2013 2014 if (!StringUtil.toBoolean(insecureAllowed)) { 2015 throw new SecurityException ("Insecured Database Object Access Not Allowed"); 2016 } 2017 } 2018 } 2019 } 2020 2021 2027 private void checkInitialized() { 2028 if (!isInitialized()) { 2029 throw new IllegalStateException ("Defineable DataObject must " + 2030 "be initialized with setDefinition() prior to use"); 2031 } 2032 2033 } 2034 2035 2040 protected boolean isInitialized() { 2041 return (getMetaData() != null); 2042 } 2043 2044 2053 protected String buildFromClause() throws DataException { 2054 FastStringBuffer fsb = FastStringBuffer.getInstance(); 2055 try { 2056 2057 JoinedDataObjectMetaData metadata = this.getJoinMetaData(); 2058 2059 ArrayList explicitRelations = new ArrayList (); 2060 ArrayList implicitRelations = new ArrayList (); 2061 Set definedSet = new TreeSet (); 2062 2063 boolean needComma = false; 2064 2065 List aliases = metadata.getAliasesInOrder(); 2066 Iterator eachAlias = aliases.iterator(); 2067 String lastAlias = (String ) eachAlias.next(); 2068 if (aliases.size() < 2) { 2069 throw new IllegalStateException ("Must have at least two tables to perform a join"); 2070 } 2071 2072 while (eachAlias.hasNext()) { 2077 String oneAlias = (String ) eachAlias.next(); 2078 JoinedDataObjectMetaData.Relation oneRelation = 2079 metadata.getRelation(lastAlias, oneAlias); 2080 2081 if (oneRelation == null) { 2082 Map m = metadata.getAllRelations(); 2086 2087 for (Iterator j = m.values().iterator(); j.hasNext();) { 2088 JoinedDataObjectMetaData.Relation testRelation = 2089 (JoinedDataObjectMetaData.Relation) j.next(); 2090 2091 if (testRelation != null) { 2092 if (oneAlias.equals(testRelation.getForeignAlias())) { 2093 oneRelation = testRelation; 2094 break; 2095 } 2096 } 2097 } 2098 2099 if (oneRelation == null) { 2100 throw new DataException("Unable to find any way to relate alias: " 2101 + oneAlias + " to the rest of the join."); 2102 } 2103 2104 if (oneRelation.getJoinType() 2105 != JoinedDataObject.UNSPECIFIED_JOIN) { 2106 throw new DataException("Alias " + oneAlias 2107 + " currently has to be " + 2108 "joined to the rest of the query through an unspecified" + 2109 " join type rather than an ANSI join"); 2110 } 2111 2112 } 2113 2114 if (oneRelation.getJoinType() 2115 == JoinedDataObject.UNSPECIFIED_JOIN) { 2116 implicitRelations.add(oneRelation); 2117 } else { 2118 definedSet.add(oneRelation.getLocalAlias()); 2119 definedSet.add(oneRelation.getForeignAlias()); 2120 explicitRelations.add(oneRelation); 2121 } 2122 2123 lastAlias = oneAlias; 2124 } 2125 2126 for (Iterator i = implicitRelations.iterator(); i.hasNext();) { 2134 if (needComma) { 2135 fsb.append(", "); 2136 } 2137 2138 JoinedDataObjectMetaData.Relation oneRelation = ( 2139 JoinedDataObjectMetaData.Relation) i.next(); 2140 String leftAlias = oneRelation.getLocalAlias(); 2141 String rightAlias = oneRelation.getForeignAlias(); 2142 2143 if (!definedSet.contains(leftAlias)) { 2144 definedSet.add(leftAlias); 2145 JDBCDataObject oneObj = (JDBCDataObject) this.myDataObjects. 2146 get(leftAlias); 2147 fsb.append(oneObj.getJDBCMetaData().getTargetSQLTable(oneObj.getDataContext())); 2148 needComma = true; 2149 2150 if (!definedSet.contains(rightAlias)) { 2151 fsb.append(", "); 2152 } 2153 } 2154 2155 if (!definedSet.contains(rightAlias)) { 2156 definedSet.add(rightAlias); 2157 JDBCDataObject oneObj = (JDBCDataObject) this.myDataObjects. 2158 get(rightAlias); 2159 fsb.append(oneObj.getJDBCMetaData().getTargetTable()); 2160 needComma = true; 2161 } 2162 2163 } 2164 2165 boolean firstJoin = true; 2169 for (Iterator i = explicitRelations.iterator(); i.hasNext();) { 2170 if (needComma) { 2171 fsb.append(", "); 2172 } 2173 needComma = false; 2174 2175 JoinedDataObjectMetaData.Relation relation = ( 2176 JoinedDataObjectMetaData.Relation) i.next(); 2177 2178 if (firstJoin) { 2179 JDBCDataObject oneObj = (JDBCDataObject) this.myDataObjects. 2180 get(relation.getLocalAlias()); 2181 fsb.append(oneObj.getJDBCMetaData().getTargetSQLTable(oneObj.getDataContext())); 2182 firstJoin = false; 2183 } 2184 2185 fsb.append(this.buildJoin(relation.getLocalAlias() 2186 , relation.getLocalField(), 2187 relation.getForeignAlias() 2188 , relation.getForeignField() 2189 , relation.getJoinType())); 2190 } 2191 2192 return fsb.toString(); 2193 } catch (DBException dbe) { 2194 log.error("Error building 'FROM' clause", dbe); 2195 throw new DataException("Error building 'FROM' clause", dbe); 2196 } catch (Exception ex) { 2197 log.error("Error building 'FROM' clause", ex); 2198 throw new DataException("Error building 'FROM' clause", ex); 2199 } finally { 2200 fsb.release(); 2201 } 2202 } 2203 2204 2214 protected String buildSelectFieldsString() throws DBException { 2215 2216 boolean needComma = false; 2217 FastStringBuffer fsb = FastStringBuffer.getInstance(); 2218 try { 2219 for (Iterator i = this.getMetaData().getFieldListArray().iterator(); 2220 i.hasNext();) { 2221 if (needComma) { 2222 fsb.append(", "); 2223 } 2224 2225 String fullFieldName = (String ) i.next(); 2226 String location[] = this.getJoinMetaData().getObjectAndField(fullFieldName); 2227 JDBCDataObject obj = (JDBCDataObject) this.myDataObjects.get(location[0]); 2228 DataFieldMetaData metadata = obj.getFieldMetaData(location[1]); 2229 if (metadata.isLongObjectType() || metadata.isVirtual()) { 2230 continue; 2231 } 2232 2233 fsb.append(obj.getJDBCMetaData().getTargetSQLTable(obj. 2234 getDataContext())); 2235 fsb.append("."); 2236 fsb.append(location[1]); 2237 needComma = true; 2238 } 2239 2240 return fsb.toString(); 2241 } finally { 2242 fsb.release(); 2243 } 2244 } 2245 2246 2247 2258 protected String buildUpdateFieldString() throws DataException { 2259 boolean needComma = false; 2260 FastStringBuffer sqlCommand = FastStringBuffer.getInstance(); 2261 try { 2262 DataFieldMetaData oneField = null; 2263 JoinedDataObjectMetaData metadata = this.getJoinMetaData(); 2264 for (Iterator i = this.getMetaData().getFieldListArray().iterator(); 2265 i.hasNext();) { 2266 String oneFieldName = (String ) i.next(); 2267 oneField = this.getFieldMetaData(oneFieldName); 2268 2269 2270 2271 if ((!oneField.isKey()) && (!oneField.isVirtual()) && 2272 (!oneField.isAutoIncremented()) 2273 && (!oneField.isBinaryObjectType())) { 2274 2275 try { 2276 this.checkField(oneFieldName 2277 , this.getDataField(oneFieldName). 2278 asString()); 2279 } catch (DBException ex) { 2280 log.error("Error validating field " + oneFieldName, ex); 2281 throw new DataException("Error validating field " 2282 + oneFieldName, ex); 2283 } 2284 2285 if (needComma) { 2286 sqlCommand.append(", "); 2287 } 2288 String location[] = metadata.getObjectAndField(oneFieldName); 2289 sqlCommand.append(((JDBCDataObject) this.myDataObjects.get(location[0])).getJDBCMetaData().getTargetSQLTable((( 2290 JDBCDataObject) this.myDataObjects.get(location[0])). 2291 getDataContext())); 2292 sqlCommand.append("."); 2293 sqlCommand.append(oneField.getName()); 2294 sqlCommand.append(" = ? "); 2295 needComma = true; 2296 } 2297 } 2298 return sqlCommand.toString(); 2299 } catch (Throwable t) { 2300 log.error("Error building update field string", t); 2301 throw new DataException("Error building update field string", t); 2302 } finally { 2303 sqlCommand.release(); 2304 } 2305 } 2306 2307 2315 protected String buildOrderByString(String sortKeys) throws DBException { 2316 2317 if (sortKeys == null || sortKeys.length() == 0) { 2318 return ""; 2319 } 2320 2321 StringTokenizer stok = new StringTokenizer (sortKeys, "|"); 2322 if (!stok.hasMoreTokens()) { 2323 return ""; 2324 } 2325 2326 FastStringBuffer fsb = FastStringBuffer.getInstance(); 2327 try { 2328 fsb.append(" ORDER BY "); 2329 boolean needComma = false; 2330 while (stok.hasMoreTokens()) { 2331 String fieldName = stok.nextToken(); 2332 String location[] = this.getJoinMetaData().getObjectAndField(fieldName); 2333 JDBCDataObject obj = (JDBCDataObject) this.myDataObjects.get(location[0]); 2334 2335 if (needComma) { 2336 fsb.append(", "); 2337 } 2338 2339 fsb.append(obj.getJDBCMetaData().getTargetSQLTable(obj. 2340 getDataContext())); 2341 fsb.append("."); 2342 fsb.append(location[1]); 2343 needComma = true; 2344 } 2345 2346 return fsb.toString(); 2347 } finally { 2348 fsb.release(); 2349 } 2350 } 2351 2352 2353 2366 protected String buildWhereClauseBuffer(boolean useAllFields 2367 , FastStringBuffer myStatement) throws 2368 DBException { 2369 2370 2371 List fields = new ArrayList (); 2372 JDBCDataObject oneObj = null; 2373 String fieldName = null; 2374 Map byTableName = new HashMap(); 2375 JoinedDataObjectMetaData metadata = this.getJoinMetaData(); 2376 2377 if (useAllFields) { 2378 2379 for (Iterator j = this.getJoinMetaData().getAliasesInOrder(). 2381 iterator(); j.hasNext();) { 2382 String oneAlias = (String ) j.next(); 2383 oneObj = (JDBCDataObject) this.myDataObjects.get(oneAlias); 2384 2385 byTableName.put(oneObj.getJDBCMetaData().getTargetSQLTable(oneObj.getDataContext()), oneObj); 2386 2387 for (Iterator i = oneObj.getMetaData().getFieldListArray(). 2388 iterator(); i.hasNext();) { 2389 fieldName = (String ) i.next(); 2390 2391 DataFieldMetaData fieldMetaData = oneObj.getFieldMetaData(fieldName); 2392 if (!fieldMetaData.isVirtual() 2393 && !fieldMetaData.isLongObjectType()) { 2394 fields.add(oneObj.getJDBCMetaData().getTargetSQLTable(oneObj.getDataContext()) + "." + 2395 fieldName); 2396 } 2397 } 2398 2399 } 2400 } else { 2401 for (Iterator eachAlias = metadata.getAliasesInOrder().iterator(); 2402 eachAlias.hasNext();) { 2403 String oneAlias = (String ) eachAlias.next(); 2404 oneObj = (JDBCDataObject) this.myDataObjects.get(oneAlias); 2405 byTableName.put(oneObj.getJDBCMetaData().getTargetSQLTable(oneObj.getDataContext()), oneObj); 2406 2407 for (Iterator i = oneObj.getMetaData().getKeyFieldListArray(). 2408 iterator(); 2409 i.hasNext();) { 2410 fieldName = (String ) i.next(); 2411 2412 DataFieldMetaData fieldMetaData = oneObj.getFieldMetaData(fieldName); 2413 if (!fieldMetaData.isVirtual() 2414 && !fieldMetaData.isBinaryObjectType()) { 2415 fields.add(oneObj.getJDBCMetaData().getTargetSQLTable(oneObj.getDataContext()) + "." + 2416 fieldName); 2417 } 2418 } 2419 2420 2421 } 2422 2423 2424 } 2425 2426 2434 boolean addWhere = true; 2435 boolean addAnd = false; 2436 String oneFieldName = null; 2437 String oneTableName = null; 2438 String oneFullName = null; 2439 String oneFieldValue = null; 2440 2441 boolean skipField = false; 2442 2443 FieldRangeParser parser = FieldRangeParser.getInstance(); 2444 for (Iterator fieldsToUse = fields.iterator(); 2445 fieldsToUse.hasNext();) { 2446 oneFullName = (String ) fieldsToUse.next(); 2447 2448 StringTokenizer stk = new StringTokenizer (oneFullName, "."); 2449 oneTableName = stk.nextToken(); 2450 oneFieldName = stk.nextToken(); 2451 2452 oneObj = (JDBCDataObject) byTableName.get(oneTableName); 2453 skipField = false; 2454 DataField oneDataField = oneObj.getDataField(oneFieldName); 2455 oneFieldValue = StringUtil.notNull(oneDataField.asString()); 2456 String rangeString = null; 2457 JDBCObjectMetaData objMetadata = oneObj.getJDBCMetaData(); 2458 2459 if (oneFieldValue == null || oneFieldValue.length() == 0) { 2460 skipField = true; 2461 } else if (oneFieldValue.length() > 0) { 2462 2463 rangeString = parser.denotesRange(oneFieldValue); 2464 if (rangeString != null && rangeString.length() > 0) { 2465 if (!parser.isValidRange(oneDataField.getFieldMetaData() 2466 , oneFieldValue)) { 2467 throw new DataException("Invalid range: " + rangeString); 2468 } 2469 } 2470 if (oneFieldValue.trim().equalsIgnoreCase("is null") || 2471 oneFieldValue.trim().equalsIgnoreCase("is not null")) { 2472 ; 2473 } else { 2474 oneFieldValue = oneObj.quoteIfNeeded(oneFieldName 2475 , rangeString); 2476 } 2477 } 2478 2479 if (oneFieldValue.equals("\'\'")) { 2480 skipField = true; 2481 } 2482 2483 if (!skipField) { 2484 try { 2486 String unalteredFieldValue = oneObj.getDataField(oneFieldName).asString(); 2487 if (rangeString != null) { 2488 boolean valid = parser.isValidRange(oneObj. 2489 getFieldMetaData(oneFieldName), unalteredFieldValue); 2490 if (!valid) { 2491 throw new DataException("Invalid field range value: " 2492 + unalteredFieldValue); 2493 } 2494 } else if (sJdbcUtil.containsWildCards(oneObj 2495 , oneFieldValue)) { 2496 Object origValue = oneObj.getDataField(oneFieldName). 2497 getValue(); 2498 2499 String [] wildcards = null; 2500 wildcards = (String []) oneObj.getConnectionPool(). 2501 getWildCardsList().toArray(new String [0]); 2502 Filter filter = new Filter(wildcards, wildcards); 2503 String valueWithoutWildCards = filter.stripFilter(unalteredFieldValue); 2504 if (!valueWithoutWildCards.equals("")) { 2506 oneObj.getDataField(oneFieldName).setValue(valueWithoutWildCards); 2507 oneObj.getDataField(oneFieldName).checkValue(); 2508 oneObj.getDataField(oneFieldName).setValue(origValue); 2509 } 2510 } else { 2511 oneObj.getDataField(oneFieldName).checkValue(); 2512 } 2513 } catch (DBException ex) { 2514 if (ex instanceof DataException) { 2515 throw ((DataException) ex); 2516 } else { 2517 throw new DataException("Error getting field value", ex); 2518 } 2519 } 2520 2521 if (addWhere) { 2522 myStatement.append(" WHERE "); 2523 addWhere = false; 2524 } 2525 if (addAnd) { 2526 myStatement.append(" AND "); 2527 } 2528 if (sJdbcUtil.containsWildCards(oneObj, oneFieldValue)) { 2529 if (caseSensitiveQuery) { 2530 myStatement.append(objMetadata.getTargetSQLTable(oneObj. 2531 getDataContext()) + "." + 2532 oneFieldName); 2533 myStatement.append(" LIKE "); 2534 myStatement.append(oneFieldValue); 2535 } else { 2536 myStatement.append("UPPER("); 2537 myStatement.append(objMetadata.getTargetSQLTable(oneObj. 2538 getDataContext()) + "." + 2539 oneFieldName); 2540 myStatement.append(") LIKE "); 2541 myStatement.append(oneFieldValue.toUpperCase()); 2542 } 2543 } else if (rangeString != null) { 2544 myStatement.append(objMetadata.getTargetSQLTable(oneObj. 2545 getDataContext()) + "." + 2546 oneFieldName); 2547 myStatement.append(" " + rangeString + " "); 2548 myStatement.append(oneFieldValue); 2549 } else { 2550 if ((oneFieldValue.trim().equalsIgnoreCase("is null")) || 2551 (oneFieldValue.trim().equalsIgnoreCase("is not null"))) { 2552 myStatement.append(objMetadata.getTargetSQLTable(oneObj. 2553 getDataContext()) + "." + 2554 oneFieldName); 2555 myStatement.append(" = "); 2556 myStatement.append(oneFieldValue); 2557 } else { 2558 if (caseSensitiveQuery) { 2559 myStatement.append(objMetadata.getTargetSQLTable(oneObj.getDataContext()) + "." + 2560 oneFieldName); 2561 myStatement.append(" = "); 2562 myStatement.append(oneFieldValue); 2563 } else { 2564 DataFieldMetaData dfmd = oneDataField. 2565 getFieldMetaData(); 2566 if (dfmd.isQuotedTextType()) { 2567 myStatement.append("UPPER("); 2568 myStatement.append(objMetadata. 2569 getTargetSQLTable(oneObj.getDataContext()) 2570 + "." + 2571 oneFieldName); 2572 myStatement.append(") = "); 2573 myStatement.append(oneFieldValue.toUpperCase()); 2574 } else { 2575 myStatement.append(objMetadata. 2576 getTargetSQLTable(oneObj.getDataContext()) 2577 + "." + 2578 oneFieldName); 2579 myStatement.append(" = "); 2580 myStatement.append(oneFieldValue); 2581 } 2582 } 2583 } 2584 } 2585 2586 addAnd = true; 2587 } 2588 2589 2590 } 2591 2592 2593 boolean needAnd = false; 2594 2595 if (!addWhere) { 2596 needAnd = true; 2597 } 2598 2599 String oneRelation = null; 2600 2601 FastStringBuffer fieldDefinitions = FastStringBuffer.getInstance(); 2606 try { 2607 for (Iterator e = metadata.getSQLRelationList().iterator(); 2608 e.hasNext();) { 2609 oneRelation = (String ) e.next(); 2610 2611 if (needAnd) { 2612 fieldDefinitions.append(" AND "); 2613 } 2614 2615 fieldDefinitions.append(oneRelation); 2616 needAnd = true; 2617 } 2618 if (log.isDebugEnabled()) { 2619 log.debug(fieldDefinitions.toString()); 2620 } 2621 2622 String result = fieldDefinitions.toString(); 2628 if (result.length() > 0) { 2629 if (addWhere) { 2630 myStatement.append(" WHERE "); 2631 } 2632 myStatement.append(result); 2633 } 2634 2635 } finally { 2636 fieldDefinitions.release(); 2637 } 2638 2639 return myStatement.toString(); 2640 } 2641 2642 2643 2649 private void formatCustomWhereClause(FastStringBuffer myStatement) throws 2650 DBException { 2651 2652 String customWhere = " " + this.customWhereClause; 2653 2654 if (myStatement.toString().indexOf(" WHERE ") != -1) { 2655 myStatement.append(" AND "); 2656 } else { 2657 myStatement.append(" WHERE "); 2658 } 2659 for (Iterator eachAlias = this.getJoinMetaData().getAliasesInOrder(). 2660 iterator(); 2661 eachAlias.hasNext();) { 2662 String oneAlias = (String ) eachAlias.next(); 2663 JDBCDataObject oneObj = (JDBCDataObject) this.myDataObjects.get(oneAlias); 2664 customWhere = 2668 StringUtil.replaceAll(customWhere, " " + oneAlias + ".", 2669 " " 2670 + oneObj.getJDBCMetaData().getTargetTable() 2671 + "."); 2672 if (customWhere.indexOf("(" + oneAlias + ".") != -1) { 2673 customWhere = 2674 StringUtil.replaceAll(customWhere, "(" + oneAlias + ".", 2675 "(" 2676 + oneObj.getJDBCMetaData().getTargetTable() 2677 + "."); 2678 } 2679 } 2680 this.setCustomWhereClause(null, false); 2681 myStatement.append(customWhere.trim()); 2682 } 2683 2684 2698 public DataObject getNestedFromFieldName(String fieldName) { 2699 String location[] = this.getJoinMetaData().getObjectAndField(fieldName); 2700 return (DataObject) this.myDataObjects.get(location[0]); 2701 } 2702 2703 2709 public DataObject[] getAllNested() { 2710 DataObject[] returnValue = new DataObject[this.myDataObjects.size()]; 2711 return (DataObject[]) this.myDataObjects.values().toArray(returnValue); 2712 } 2713 2714 2715 2716 2728 public String getFieldFromNestedName(String fieldName) { 2729 String location[] = this.getJoinMetaData().getObjectAndField(fieldName); 2730 return location[1]; 2731 } 2732 2733 2734 2742 public String getField(String fieldName) throws DBException { 2743 return this.getDataField(fieldName).asString(); 2744 } 2745 2746 2755 public synchronized void setConnection(DBConnection newConnection) throws 2756 DBException { 2757 setConnection(newConnection, newConnection.getDataContext()); 2758 } 2759 2760 2761 2778 public synchronized void setConnection(DBConnection newConnection, 2779 String setupTablesContext) throws 2780 DBException { 2781 localConnection = newConnection; 2782 this.setDataContext(setupTablesContext); 2783 } 2784 2785 2792 public void setGlobalMask(Pattern newMask) { 2793 this.setGlobalMask(newMask); 2794 } 2795 2796 2801 public Pattern getGlobalMask() { 2802 return this.getGlobalMask(); 2803 } 2804 2805 2806 2811 public boolean isGlobalMasked() { 2812 return this.isGlobalMasked(); 2813 } 2814 2815 2816 2821 public void setFieldsWithDefaults() throws DataException { 2822 for (Iterator j = this.getJoinMetaData().getAliasesInOrder(). 2823 iterator(); j.hasNext();) { 2824 String oneAlias = (String ) j.next(); 2825 JDBCDataObject oneObj = (JDBCDataObject) this.myDataObjects.get(oneAlias); 2826 oneObj.setFieldsWithDefaults(); 2827 } 2828 } 2829 2830 2831} 2832 | Popular Tags |