001/* 002 * The Kuali Financial System, a comprehensive financial management system for higher education. 003 * 004 * Copyright 2005-2014 The Kuali Foundation 005 * 006 * This program is free software: you can redistribute it and/or modify 007 * it under the terms of the GNU Affero General Public License as 008 * published by the Free Software Foundation, either version 3 of the 009 * License, or (at your option) any later version. 010 * 011 * This program is distributed in the hope that it will be useful, 012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 014 * GNU Affero General Public License for more details. 015 * 016 * You should have received a copy of the GNU Affero General Public License 017 * along with this program. If not, see <http://www.gnu.org/licenses/>. 018 */ 019package org.kuali.kfs.sys.dataaccess.impl; 020 021import java.sql.DatabaseMetaData; 022import java.sql.ResultSet; 023import java.sql.SQLException; 024 025import org.apache.commons.beanutils.PropertyUtils; 026import org.apache.log4j.Logger; 027import org.apache.ojb.broker.metadata.ClassDescriptor; 028import org.kuali.kfs.sys.dataaccess.FieldMetaData; 029import org.kuali.rice.core.framework.persistence.ojb.conversion.OjbKualiEncryptDecryptFieldConversion; 030import org.kuali.rice.krad.bo.BusinessObject; 031import org.kuali.rice.krad.bo.PersistableBusinessObject; 032import org.springframework.jdbc.support.DatabaseMetaDataCallback; 033import org.springframework.jdbc.support.MetaDataAccessException; 034 035public class FieldMetaDataImpl implements DatabaseMetaDataCallback, FieldMetaData { 036 private static final Logger LOG = Logger.getLogger(FieldMetaDataImpl.class); 037 038 private Class businessObjectClass; 039 private String propertyName; 040 041 private String tableName; 042 private String columnName; 043 private String dataType; 044 private int length; 045 private int decimalPlaces; 046 private boolean encrypted; 047 048 public FieldMetaDataImpl(Class businessObjectClass, String propertyName) { 049 this.businessObjectClass = businessObjectClass; 050 this.propertyName = propertyName; 051 } 052 053 public Object processMetaData(DatabaseMetaData databaseMetaData) throws SQLException, MetaDataAccessException { 054 Class workingBusinessObjectClass = businessObjectClass; 055 String workingPropertyName = propertyName; 056 while (workingPropertyName.contains(".")) { 057 try { 058 workingBusinessObjectClass = org.apache.ojb.broker.metadata.MetadataManager.getInstance().getGlobalRepository().getDescriptorFor(workingBusinessObjectClass).getObjectReferenceDescriptorByName(workingPropertyName.substring(0, workingPropertyName.indexOf("."))).getItemClass(); 059 } 060 catch (Exception e1) { 061 LOG.debug(new StringBuffer("Unable to get property type via reference descriptor for property ").append(workingPropertyName.substring(0, workingPropertyName.indexOf("."))).append(" of BusinessObject class ").append(workingBusinessObjectClass).toString(), e1); 062 try { 063 workingBusinessObjectClass = org.apache.ojb.broker.metadata.MetadataManager.getInstance().getGlobalRepository().getDescriptorFor(workingBusinessObjectClass).getCollectionDescriptorByName(workingPropertyName.substring(0, workingPropertyName.indexOf("."))).getItemClass(); 064 } 065 catch (Exception e2) { 066 LOG.debug(new StringBuffer("Unable to get property type via collection descriptor of property ").append(workingPropertyName.substring(0, workingPropertyName.indexOf("."))).append(" of BusinessObject class ").append(workingBusinessObjectClass).toString(), e2); 067 BusinessObject businessObject = null; 068 try { 069 businessObject = (BusinessObject)workingBusinessObjectClass.newInstance(); 070 } 071 catch (Exception e3) { 072 if (LOG.isDebugEnabled()) { 073 LOG.debug("Unable to instantiate BusinessObject class " + workingBusinessObjectClass, e3); 074 } 075 return populateAndReturnNonPersistableInstance(); 076 } 077 try { 078 workingBusinessObjectClass = PropertyUtils.getPropertyType(businessObject, workingPropertyName.substring(0, workingPropertyName.indexOf("."))); 079 } 080 catch (Exception e4) { 081 LOG.debug(new StringBuffer("Unable to get type of property ").append(workingPropertyName.substring(0, workingPropertyName.indexOf("."))).append(" for BusinessObject class ").append(workingBusinessObjectClass).toString(), e4); 082 return populateAndReturnNonPersistableInstance(); 083 } 084 } 085 } 086 if (workingBusinessObjectClass == null) { 087 return populateAndReturnNonPersistableInstance(); 088 } 089 else { 090 workingPropertyName = workingPropertyName.substring(workingPropertyName.indexOf(".") + 1); 091 } 092 } 093 if (!PersistableBusinessObject.class.isAssignableFrom(workingBusinessObjectClass)) { 094 return populateAndReturnNonPersistableInstance(); 095 } 096 ClassDescriptor classDescriptor = org.apache.ojb.broker.metadata.MetadataManager.getInstance().getGlobalRepository().getDescriptorFor(workingBusinessObjectClass); 097 if (classDescriptor == null) { 098 return populateAndReturnNonPersistableInstance(); 099 } 100 tableName = classDescriptor.getFullTableName(); 101 if (classDescriptor.getFieldDescriptorByName(workingPropertyName) == null) { 102 return populateAndReturnNonPersistableInstance(); 103 } 104 columnName = classDescriptor.getFieldDescriptorByName(workingPropertyName).getColumnName(); 105 ResultSet resultSet = databaseMetaData.getColumns(null, null, tableName, columnName); 106 if (resultSet.next()) { 107 dataType = resultSet.getString("TYPE_NAME"); 108 length = resultSet.getInt("COLUMN_SIZE"); 109 decimalPlaces = resultSet.getInt("DECIMAL_DIGITS"); 110 encrypted = classDescriptor.getFieldDescriptorByName(workingPropertyName).getFieldConversion() instanceof OjbKualiEncryptDecryptFieldConversion; 111 } 112 resultSet.close(); 113 return this; 114 } 115 116 protected FieldMetaData populateAndReturnNonPersistableInstance() { 117 tableName = "N/A"; 118 columnName = tableName; 119 dataType = tableName; 120 length = 0; 121 decimalPlaces = 0; 122 encrypted = false; 123 return this; 124 } 125 126 public String getTableName() { 127 return tableName; 128 } 129 130 public String getColumnName() { 131 return columnName; 132 } 133 134 public String getDataType() { 135 return dataType; 136 } 137 138 public int getLength() { 139 return length; 140 } 141 142 public int getDecimalPlaces() { 143 return decimalPlaces; 144 } 145 146 public boolean isEncrypted() { 147 return encrypted; 148 } 149}