Java tutorial
/* * The Kuali Financial System, a comprehensive financial management system for higher education. * * Copyright 2005-2014 The Kuali Foundation * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package org.kuali.kfs.sys.context; import java.lang.reflect.Field; import java.sql.Connection; import java.sql.ResultSet; import java.sql.Statement; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import java.util.TreeSet; import javax.sql.DataSource; import org.apache.commons.lang.StringUtils; import org.apache.log4j.Logger; import org.kuali.kfs.sys.ConfigureContext; import org.kuali.kfs.sys.document.datadictionary.FinancialSystemMaintenanceDocumentEntry; import org.kuali.kfs.sys.suite.AnnotationTestSuite; import org.kuali.kfs.sys.suite.PreCommitSuite; import org.kuali.rice.core.api.mo.common.active.MutableInactivatable; import org.kuali.rice.kns.datadictionary.BusinessObjectEntry; import org.kuali.rice.kns.datadictionary.InquiryDefinition; import org.kuali.rice.kns.datadictionary.InquirySectionDefinition; import org.kuali.rice.kns.datadictionary.LookupDefinition; import org.kuali.rice.kns.datadictionary.MaintainableSectionDefinition; import org.kuali.rice.krad.datadictionary.AttributeDefinition; import org.kuali.rice.krad.datadictionary.DataDictionary; import org.kuali.rice.krad.datadictionary.DocumentEntry; import org.kuali.rice.krad.service.DataDictionaryService; import org.springframework.beans.factory.NoSuchBeanDefinitionException; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.support.KualiDefaultListableBeanFactory; @AnnotationTestSuite(PreCommitSuite.class) @ConfigureContext public class DataDictionaryConfigurationTest extends KualiTestBase { private static final Logger LOG = Logger.getLogger(DataDictionaryConfigurationTest.class); private DataDictionary dataDictionary; public final static String KFS_PACKAGE_NAME_PREFIX = "org.kuali.kfs"; public final static String BUSINESS_OBJECT_PATH_QUALIFIER = "businessobject/datadictionary"; public final static String DOCUMENT_PATH_QUALIFIER = "document/datadictionary"; public final static String RICE_PACKAGE_NAME_PREFIX = "org.kuali.rice"; public final static String INACTIVATEABLE_INTERFACE_CLASS = MutableInactivatable.class.getName(); public final static String ACTIVE_FIELD_NAME = "active"; public void testAllDataDictionaryDocumentTypesExistInWorkflowDocumentTypeTable() throws Exception { HashSet<String> workflowDocumentTypeNames = new HashSet<String>(); DataSource mySource = SpringContext.getBean(DataSource.class); Connection dbCon = null; try { dbCon = mySource.getConnection(); Statement dbAsk = dbCon.createStatement(); ResultSet dbAnswer = dbAsk.executeQuery("select DOC_TYP_NM from KREW_DOC_TYP_T where CUR_IND = 1"); while (dbAnswer.next()) { String docName = dbAnswer.getString(1); if (StringUtils.isNotBlank(docName)) { workflowDocumentTypeNames.add(docName); } } } catch (Exception e) { throw (e); } // Using HashSet since duplicate objects would otherwise be returned HashSet<DocumentEntry> documentEntries = new HashSet<DocumentEntry>( dataDictionary.getDocumentEntries().values()); List<String> ddEntriesWithMissingTypes = new ArrayList<String>(); for (DocumentEntry documentEntry : documentEntries) { String name = documentEntry.getDocumentTypeName(); String testName = new String(" "); if (documentEntry instanceof FinancialSystemMaintenanceDocumentEntry) { testName = ((FinancialSystemMaintenanceDocumentEntry) documentEntry).getBusinessObjectClass() .getName(); } else { testName = documentEntry.getDocumentClass().getName(); } if (!workflowDocumentTypeNames.contains(name) && !"RiceUserMaintenanceDocument".equals(name) && !testName.contains("rice")) { ddEntriesWithMissingTypes.add(name); } else { workflowDocumentTypeNames.remove(name); } } if (workflowDocumentTypeNames.size() > 0) { try { //If documents are parent docs, then they aren't superfluous. String queryString = "select distinct doc_typ_nm from KREW_DOC_TYP_T" + " where doc_typ_id in (select parnt_id from KREW_DOC_TYP_T" + " where actv_ind = 1" + " and cur_ind = 1)"; Statement dbAsk = dbCon.createStatement(); ResultSet dbAnswer = dbAsk.executeQuery(queryString); while (dbAnswer.next()) { String docName = dbAnswer.getString(1); if (StringUtils.isNotBlank(docName)) { workflowDocumentTypeNames.remove(docName); } } } catch (Exception e) { throw (e); } System.err.print("superfluousTypesDefinedInWorkflowDatabase: " + workflowDocumentTypeNames); } assertEquals("documentTypesNotDefinedInWorkflowDatabase: " + ddEntriesWithMissingTypes, 0, ddEntriesWithMissingTypes.size()); } private final static List<String> INACTIVATEABLE_LOOKUP_IGNORE_CLASSES = new ArrayList<String>(); static { // org.kuali.kfs.coa.businessobject.Account is excepted from testActiveFieldExistInLookupAndResultSection because it uses the active-derived Closed? indicator instead (KFSMI-1393) INACTIVATEABLE_LOOKUP_IGNORE_CLASSES.add("org.kuali.kfs.coa.businessobject.Account"); INACTIVATEABLE_LOOKUP_IGNORE_CLASSES .add("org.kuali.kfs.module.bc.businessobject.BudgetConstructionPosition"); INACTIVATEABLE_LOOKUP_IGNORE_CLASSES .add("org.kuali.kfs.module.bc.businessobject.PendingBudgetConstructionAppointmentFunding"); } private static final List<String> INACTIVATEABLE_LOOKUP_IGNORE_PACKAGES = new ArrayList<String>(); static { INACTIVATEABLE_LOOKUP_IGNORE_PACKAGES.add("org.kuali.kfs.pdp.businessobject"); INACTIVATEABLE_LOOKUP_IGNORE_PACKAGES.add("org.kuali.kfs.module.external.kc.businessobject"); } public void testActiveFieldExistInLookupAndResultSection() throws Exception { List<Class<?>> noActiveFieldClassList = new ArrayList<Class<?>>(); List<Class<?>> notImplementInactivatableList = new ArrayList<Class<?>>(); List<Class<?>> defaultValueWrongList = new ArrayList<Class<?>>(); for (org.kuali.rice.krad.datadictionary.BusinessObjectEntry kradBusinessObjectEntry : dataDictionary .getBusinessObjectEntries().values()) { BusinessObjectEntry businessObjectEntry = (BusinessObjectEntry) kradBusinessObjectEntry; if (!businessObjectEntry.getBusinessObjectClass().getName().startsWith(RICE_PACKAGE_NAME_PREFIX) && !INACTIVATEABLE_LOOKUP_IGNORE_CLASSES .contains(businessObjectEntry.getBusinessObjectClass().getName()) && !INACTIVATEABLE_LOOKUP_IGNORE_PACKAGES .contains(businessObjectEntry.getBusinessObjectClass().getPackage().getName())) { try { LookupDefinition lookupDefinition = businessObjectEntry.getLookupDefinition(); // Class implements MutableInactivatable but active field not used on Lookup. if (Class.forName(INACTIVATEABLE_INTERFACE_CLASS) .isAssignableFrom(businessObjectEntry.getBusinessObjectClass())) { if (lookupDefinition != null && !(lookupDefinition.getLookupFieldNames().contains(ACTIVE_FIELD_NAME) && lookupDefinition.getResultFieldNames().contains(ACTIVE_FIELD_NAME))) { noActiveFieldClassList.add(businessObjectEntry.getBusinessObjectClass()); if (lookupDefinition.getLookupField(ACTIVE_FIELD_NAME) != null) { //Default must be 'Y' not 'true' if (!StringUtils.equals( lookupDefinition.getLookupField(ACTIVE_FIELD_NAME).getDefaultValue(), "Y")) { defaultValueWrongList.add(businessObjectEntry.getBusinessObjectClass()); } } } } else { // Lookup show active flag, but class does not implement MutableInactivatable. if (lookupDefinition != null && (lookupDefinition.getLookupFieldNames().contains(ACTIVE_FIELD_NAME) || lookupDefinition.getResultFieldNames().contains(ACTIVE_FIELD_NAME))) { notImplementInactivatableList.add(businessObjectEntry.getBusinessObjectClass()); } } } catch (ClassNotFoundException e) { throw (e); } } } String errorString = ""; if (noActiveFieldClassList.size() != 0) errorString = errorString + "Missing Active Field: " + formatErrorStringGroupByModule(noActiveFieldClassList); if (notImplementInactivatableList.size() != 0) errorString = errorString + "Inactivatable not implemented: " + formatErrorStringGroupByModule(notImplementInactivatableList); if (defaultValueWrongList.size() != 0) errorString = errorString + "Wrong default value: " + formatErrorStringGroupByModule(defaultValueWrongList); assertEquals(errorString, 0, noActiveFieldClassList.size() + notImplementInactivatableList.size() + defaultValueWrongList.size()); } private String formatErrorStringGroupByModule(List<Class<?>> failedList) { Map<String, Set<String>> listMap = new HashMap<String, Set<String>>(); String module = null; String itemName = null; for (Class<?> item : failedList) { itemName = item.getName(); module = itemName.substring(0, itemName.lastIndexOf('.')); if (!listMap.keySet().contains(module)) { listMap.put(module, new HashSet<String>()); } listMap.get(module).add(itemName.substring(itemName.lastIndexOf('.') + 1)); } String tempString = ""; for (String moduleName : listMap.keySet()) { tempString = tempString + "Module :" + moduleName + "\n"; for (String errorClass : (Set<String>) listMap.get(moduleName)) { tempString = tempString + " " + errorClass + "\n"; } } return "\n" + tempString; } public void testAllBusinessObjectsHaveObjectLabel() throws Exception { List<Class<?>> noObjectLabelClassList = new ArrayList<Class<?>>(); for (org.kuali.rice.krad.datadictionary.BusinessObjectEntry kradBusinessObjectEntry : dataDictionary .getBusinessObjectEntries().values()) { BusinessObjectEntry businessObjectEntry = (BusinessObjectEntry) kradBusinessObjectEntry; if (StringUtils.isBlank(businessObjectEntry.getObjectLabel())) { noObjectLabelClassList.add(businessObjectEntry.getBusinessObjectClass()); } } assertEquals(noObjectLabelClassList.toString(), 0, noObjectLabelClassList.size()); } public void testAllParentBeansAreAbstract() throws Exception { Field f = dataDictionary.getClass().getDeclaredField("ddBeans"); f.setAccessible(true); KualiDefaultListableBeanFactory ddBeans = (KualiDefaultListableBeanFactory) f.get(dataDictionary); List<String> failingBeanNames = new ArrayList<String>(); for (String beanName : ddBeans.getBeanDefinitionNames()) { BeanDefinition beanDef = ddBeans.getMergedBeanDefinition(beanName); String beanClass = beanDef.getBeanClassName(); // skip Rice classes if (beanClass != null && beanClass.startsWith("org.kuali.rice")) { continue; } if ((beanName.endsWith("-parentBean") || beanName.endsWith("-baseBean")) && !beanDef.isAbstract()) { failingBeanNames.add(beanName + " : " + beanDef.getResourceDescription() + "\n"); } } assertEquals("The following parent beans are not defined as abstract:\n" + failingBeanNames, 0, failingBeanNames.size()); } public void testBusinessObjectEntriesShouldHaveParentBeans() throws Exception { somethingShouldHaveParentBeans(BusinessObjectEntry.class, new ArrayList<String>()); } public void testDocumentEntriesShouldHaveParentBeans() throws Exception { somethingShouldHaveParentBeans(DocumentEntry.class, new ArrayList<String>()); } protected static final List<String> EXCLUDED_ATTRIBUTE_DEFINITIONS = new ArrayList<String>(); static { EXCLUDED_ATTRIBUTE_DEFINITIONS.add("Country-"); EXCLUDED_ATTRIBUTE_DEFINITIONS.add("County-"); EXCLUDED_ATTRIBUTE_DEFINITIONS.add("State-"); EXCLUDED_ATTRIBUTE_DEFINITIONS.add("PostalCode-"); EXCLUDED_ATTRIBUTE_DEFINITIONS.add("PersonImpl-"); EXCLUDED_ATTRIBUTE_DEFINITIONS.add("RoleMemberBo-"); EXCLUDED_ATTRIBUTE_DEFINITIONS.add("KimAttributes-"); EXCLUDED_ATTRIBUTE_DEFINITIONS.add("KimDocRoleMember-"); EXCLUDED_ATTRIBUTE_DEFINITIONS.add("DocRoleMember-"); EXCLUDED_ATTRIBUTE_DEFINITIONS.add("Responsibility-"); EXCLUDED_ATTRIBUTE_DEFINITIONS.add("PermissionBo-"); EXCLUDED_ATTRIBUTE_DEFINITIONS.add("PermissionImpl-"); EXCLUDED_ATTRIBUTE_DEFINITIONS.add("UberPermission-"); EXCLUDED_ATTRIBUTE_DEFINITIONS.add("ReviewResponsibility-"); EXCLUDED_ATTRIBUTE_DEFINITIONS.add("ResponsibilityImpl-"); EXCLUDED_ATTRIBUTE_DEFINITIONS.add("UberPermissionBo-"); EXCLUDED_ATTRIBUTE_DEFINITIONS.add("RuleTemplateAttribute-"); EXCLUDED_ATTRIBUTE_DEFINITIONS.add("-versionNumber"); } public void testAttributeDefinitionsShouldHaveParentBeans() throws Exception { somethingShouldHaveParentBeans(AttributeDefinition.class, EXCLUDED_ATTRIBUTE_DEFINITIONS); } public void testMaintenanceSectionsShouldHaveParentBeans() throws Exception { somethingShouldHaveParentBeans(MaintainableSectionDefinition.class, new ArrayList<String>()); } public void testInquirySectionsShouldHaveParentBeans() throws Exception { somethingShouldHaveParentBeans(InquirySectionDefinition.class, new ArrayList<String>()); } public void testLookupDefinitionsShouldHaveParentBeans() throws Exception { somethingShouldHaveParentBeans(LookupDefinition.class, new ArrayList<String>()); } public void testInquiryDefinitionsShouldHaveParentBeans() throws Exception { somethingShouldHaveParentBeans(InquiryDefinition.class, new ArrayList<String>()); } protected boolean doesBeanNameMatchList(String beanName, List<String> exclusions) { for (String excl : exclusions) { if (beanName.contains(excl)) { return true; } } return false; } protected void somethingShouldHaveParentBeans(Class<?> baseClass, List<String> exclusions) throws Exception { Field f = dataDictionary.getClass().getDeclaredField("ddBeans"); f.setAccessible(true); KualiDefaultListableBeanFactory ddBeans = (KualiDefaultListableBeanFactory) f.get(dataDictionary); List<String> failingBeanNames = new ArrayList<String>(); for (String beanName : ddBeans.getBeanDefinitionNames()) { if (doesBeanNameMatchList(beanName, exclusions)) { continue; } BeanDefinition beanDef = ddBeans.getMergedBeanDefinition(beanName); String beanClass = beanDef.getBeanClassName(); if (beanClass == null) { System.err.println("ERROR: Bean " + beanName + " has a null class."); } if (!beanDef.isAbstract() && beanClass != null && baseClass.isAssignableFrom(Class.forName(beanClass))) { try { BeanDefinition parentBean = ddBeans.getBeanDefinition(beanName + "-parentBean"); } catch (NoSuchBeanDefinitionException ex) { failingBeanNames.add(beanName + " : " + beanDef.getResourceDescription() + "\n"); } } } assertEquals("The following " + baseClass.getSimpleName() + " beans do not have \"-parentBean\"s:\n" + failingBeanNames, 0, failingBeanNames.size()); } private void reportErrorAttribute(Map<String, Set<String>> reports, AttributeDefinition attributeDefinition, String boClassName) { Set<String> attributeSet = reports.containsKey(boClassName) ? reports.get(boClassName) : new TreeSet<String>(); attributeSet.add(attributeDefinition.getName()); reports.put(boClassName, attributeSet); } private StringBuilder convertReportsAsText(Map<String, Set<String>> reports) { StringBuilder reportsAsText = new StringBuilder(); for (String key : new TreeSet<String>(reports.keySet())) { reportsAsText.append(key + "\n"); for (String value : reports.get(key)) { reportsAsText.append("\t--").append(value).append("\n"); } } return reportsAsText; } private void printReport(Map<String, Set<String>> reports) { StringBuilder reportsAsText = convertReportsAsText(reports); System.out.println(reportsAsText); LOG.info("\n" + reportsAsText); } @Override protected void setUp() throws Exception { super.setUp(); dataDictionary = SpringContext.getBean(DataDictionaryService.class).getDataDictionary(); } }