001 /*
002 * Copyright 2011 The Kuali Foundation.
003 *
004 * Licensed under the Educational Community License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.opensource.org/licenses/ecl2.php
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016 package org.kuali.kfs.sys.dataaccess.impl;
017
018 import java.lang.reflect.InvocationTargetException;
019 import java.sql.DatabaseMetaData;
020 import java.sql.ResultSet;
021 import java.sql.SQLException;
022 import java.util.Collection;
023
024 import org.apache.commons.beanutils.PropertyUtils;
025 import org.apache.log4j.Logger;
026 import org.apache.ojb.broker.metadata.ClassDescriptor;
027 import org.kuali.kfs.sys.dataaccess.FieldMetaData;
028 import org.kuali.rice.kns.bo.BusinessObject;
029 import org.kuali.rice.kns.bo.PersistableBusinessObject;
030 import org.kuali.rice.kns.util.OjbKualiEncryptDecryptFieldConversion;
031 import org.springframework.jdbc.support.DatabaseMetaDataCallback;
032 import org.springframework.jdbc.support.MetaDataAccessException;
033
034 public class FieldMetaDataImpl implements DatabaseMetaDataCallback, FieldMetaData {
035 private static final Logger LOG = Logger.getLogger(FieldMetaDataImpl.class);
036
037 private Class businessObjectClass;
038 private String propertyName;
039
040 private String tableName;
041 private String columnName;
042 private String dataType;
043 private int length;
044 private int decimalPlaces;
045 private boolean encrypted;
046
047 public FieldMetaDataImpl(Class businessObjectClass, String propertyName) {
048 this.businessObjectClass = businessObjectClass;
049 this.propertyName = propertyName;
050 }
051
052 public Object processMetaData(DatabaseMetaData databaseMetaData) throws SQLException, MetaDataAccessException {
053 Class workingBusinessObjectClass = businessObjectClass;
054 String workingPropertyName = propertyName;
055 while (workingPropertyName.contains(".")) {
056 try {
057 workingBusinessObjectClass = org.apache.ojb.broker.metadata.MetadataManager.getInstance().getGlobalRepository().getDescriptorFor(workingBusinessObjectClass).getObjectReferenceDescriptorByName(workingPropertyName.substring(0, workingPropertyName.indexOf("."))).getItemClass();
058 }
059 catch (Exception e1) {
060 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);
061 try {
062 workingBusinessObjectClass = org.apache.ojb.broker.metadata.MetadataManager.getInstance().getGlobalRepository().getDescriptorFor(workingBusinessObjectClass).getCollectionDescriptorByName(workingPropertyName.substring(0, workingPropertyName.indexOf("."))).getItemClass();
063 }
064 catch (Exception e2) {
065 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);
066 BusinessObject businessObject = null;
067 try {
068 businessObject = (BusinessObject)workingBusinessObjectClass.newInstance();
069 }
070 catch (Exception e3) {
071 LOG.debug("Unable to instantiate BusinessObject class " + workingBusinessObjectClass, e3);
072 return populateAndReturnNonPersistableInstance();
073 }
074 try {
075 workingBusinessObjectClass = PropertyUtils.getPropertyType(businessObject, workingPropertyName.substring(0, workingPropertyName.indexOf(".")));
076 }
077 catch (Exception e4) {
078 LOG.debug(new StringBuffer("Unable to get type of property ").append(workingPropertyName.substring(0, workingPropertyName.indexOf("."))).append(" for BusinessObject class ").append(workingBusinessObjectClass).toString(), e4);
079 return populateAndReturnNonPersistableInstance();
080 }
081 }
082 }
083 if (workingBusinessObjectClass == null) {
084 return populateAndReturnNonPersistableInstance();
085 }
086 else {
087 workingPropertyName = workingPropertyName.substring(workingPropertyName.indexOf(".") + 1);
088 }
089 }
090 if (!PersistableBusinessObject.class.isAssignableFrom(workingBusinessObjectClass)) {
091 return populateAndReturnNonPersistableInstance();
092 }
093 ClassDescriptor classDescriptor = org.apache.ojb.broker.metadata.MetadataManager.getInstance().getGlobalRepository().getDescriptorFor(workingBusinessObjectClass);
094 if (classDescriptor == null) {
095 return populateAndReturnNonPersistableInstance();
096 }
097 tableName = classDescriptor.getFullTableName();
098 if (classDescriptor.getFieldDescriptorByName(workingPropertyName) == null) {
099 return populateAndReturnNonPersistableInstance();
100 }
101 columnName = classDescriptor.getFieldDescriptorByName(workingPropertyName).getColumnName();
102 ResultSet resultSet = databaseMetaData.getColumns(null, null, tableName, columnName);
103 if (resultSet.next()) {
104 dataType = resultSet.getString("TYPE_NAME");
105 length = resultSet.getInt("COLUMN_SIZE");
106 decimalPlaces = resultSet.getInt("DECIMAL_DIGITS");
107 encrypted = classDescriptor.getFieldDescriptorByName(workingPropertyName).getFieldConversion() instanceof OjbKualiEncryptDecryptFieldConversion;
108 }
109 resultSet.close();
110 return this;
111 }
112
113 protected FieldMetaData populateAndReturnNonPersistableInstance() {
114 tableName = "N/A";
115 columnName = tableName;
116 dataType = tableName;
117 length = 0;
118 decimalPlaces = 0;
119 encrypted = false;
120 return this;
121 }
122
123 public String getTableName() {
124 return tableName;
125 }
126
127 public String getColumnName() {
128 return columnName;
129 }
130
131 public String getDataType() {
132 return dataType;
133 }
134
135 public int getLength() {
136 return length;
137 }
138
139 public int getDecimalPlaces() {
140 return decimalPlaces;
141 }
142
143 public boolean isEncrypted() {
144 return encrypted;
145 }
146 }