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    }