001 /** 002 * Copyright 2004-2013 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.student.datadictionary.util; 017 018 import java.io.File; 019 import java.io.FileNotFoundException; 020 import java.io.IOException; 021 import java.util.ArrayList; 022 import java.util.Collection; 023 import java.util.HashSet; 024 import java.util.LinkedHashMap; 025 import java.util.LinkedHashSet; 026 import java.util.List; 027 import java.util.Map; 028 import java.util.Set; 029 030 import org.apache.commons.io.FileUtils; 031 import org.apache.commons.lang.exception.ExceptionUtils; 032 import org.kuali.rice.krad.datadictionary.DataObjectEntry; 033 import org.slf4j.Logger; 034 import org.slf4j.LoggerFactory; 035 import org.springframework.context.support.ClassPathXmlApplicationContext; 036 037 public class DictionaryTesterHelper { 038 039 private static final Logger log = LoggerFactory.getLogger(DictionaryTesterHelper.class); 040 041 private String outputDir; 042 private Collection<String> inputFiles; 043 private List<String> supportFiles; 044 045 private Map<String, List<String>>inputFileToBeanNameMap = new LinkedHashMap<String, List<String>>(); 046 047 private Set<String> missingDictionaryFiles; 048 049 private Set<String> invalidDictionaryFiles; 050 051 052 053 public DictionaryTesterHelper(String outputDir, Collection<String> inputFiles, 054 List<String> supportFiles) { 055 this.outputDir = outputDir; 056 this.inputFiles = inputFiles; 057 this.supportFiles = supportFiles; 058 } 059 060 // public void loadApplicationContext() { 061 // System.out.println 062 // ("DictionaryTesterHelper: begin loading application context"); 063 // 064 // ac = new PathValidatingClassPathXmlApplicationContext(); 065 // 066 // for (String candidateConfigFile : this.configFiles) { 067 // ac.addContextFile(candidateConfigFile); 068 // } 069 // 070 // ac.buildApplicationContext(); 071 // System.out.println 072 // ("DictionaryTesterHelper: end loading application context"); 073 // } 074 // 075 // public Map<String, DataObjectEntry> getDataObjectEntryBeans () { 076 // return (Map<String, DataObjectEntry>) 077 // ac.getBeansOfType(DataObjectEntry.class); 078 // } 079 080 public void doTest(String projectVersion, String formattedDate) { 081 082 missingDictionaryFiles = new LinkedHashSet<String>(); 083 084 invalidDictionaryFiles = new LinkedHashSet<String>(); 085 086 for (String inputFile : inputFiles) { 087 088 List<String> contextFiles = new ArrayList<String>(); 089 090 contextFiles.add(inputFile); 091 contextFiles.addAll(supportFiles); 092 093 ClassPathXmlApplicationContext ac; 094 try { 095 log.info("Starting on inputFile: " + inputFile); 096 097 ac = new ClassPathXmlApplicationContext( 098 contextFiles.toArray(new String[0])); 099 } catch (Exception e) { 100 log.warn ("FAILED to valildate file: " + inputFile, e); 101 102 Throwable cause = e.getCause(); 103 if (cause != null && cause instanceof FileNotFoundException) { 104 missingDictionaryFiles.add(inputFile); 105 } 106 else { 107 // In this case we should create a place holder page 108 writePlaceholderPage(inputFile, cause); 109 invalidDictionaryFiles.add(inputFile); 110 } 111 continue; // skip over this file. 112 } 113 114 ArrayList<String> associatedBeanNameList = new ArrayList<String>(); 115 116 Map<String, DataObjectEntry> beansOfType = ac 117 .getBeansOfType(DataObjectEntry.class); 118 119 for (String beanId : beansOfType.keySet()) { 120 121 try { 122 DataObjectEntry doe = beansOfType.get(beanId); 123 if ("org.kuali.rice.krad.bo.AttributeReferenceDummy".equals(doe 124 .getFullClassName())) { 125 continue; 126 } 127 128 associatedBeanNameList.add(beanId); 129 130 log.info("Processing data object entry: " 131 + doe.getDataObjectClass().getName()); 132 DictionaryValidator validator = new DictionaryValidator(doe, 133 new HashSet<DataObjectEntry>()); 134 List<String> errors = validator.validate(); 135 if (errors != null) { 136 if (!errors.isEmpty()) { 137 throw new IllegalArgumentException( 138 "Errors validating bean " + beanId + "\n" 139 + this.formatAsString(errors)); 140 } 141 } 142 String outputFileName = beanId + ".html"; 143 String fullOutputFileName = this.outputDir + "/" 144 + outputFileName; 145 DictionaryFormatter formatter = new DictionaryFormatter(doe, 146 beansOfType, beanId, fullOutputFileName); 147 148 formatter.formatForHtml(projectVersion, formattedDate); 149 150 151 } catch (Exception e) { 152 153 log.warn("FAILED to format dictionary page for: " + beanId, e); 154 invalidDictionaryFiles.add(inputFile); 155 continue; 156 } 157 158 } 159 160 if (associatedBeanNameList.size() > 0) { 161 inputFileToBeanNameMap.put(inputFile, associatedBeanNameList); 162 } 163 164 log.info("Finished processing inputFile: " + inputFile); 165 } 166 } 167 168 /* 169 * In some cases like where spring fails to parse the input file we will want to write a place holder with the cause. 170 * 171 */ 172 private void writePlaceholderPage(String inputFile, Throwable cause) { 173 174 String[] parts = inputFile.split ("-"); 175 176 String beanId = parts[1]; 177 178 String outputFileName = beanId + ".html"; 179 String fullOutputFileName = this.outputDir + "/" 180 + outputFileName; 181 182 try { 183 FileUtils.writeStringToFile(new File (fullOutputFileName), "<html><body><h1>Failed To Generate Page due to Error in Dictionary File: "+inputFile+"</h1>" +ExceptionUtils.getFullStackTrace(cause) + "</body></html>", false); 184 } catch (IOException e) { 185 log.warn("failed to write placeholder page: " + inputFile, e); 186 } 187 } 188 189 private String formatAsString(List<String> errors) { 190 int i = 0; 191 StringBuilder builder = new StringBuilder(); 192 for (String error : errors) { 193 i++; 194 builder.append(i).append(". ").append(error).append("\n"); 195 } 196 return builder.toString(); 197 } 198 199 /** 200 * @return the inputFileToBeanNameMap 201 */ 202 public Map<String, List<String>> getInputFileToBeanNameMap() { 203 return inputFileToBeanNameMap; 204 } 205 206 /** 207 * @return the missingDictionaryFiles 208 */ 209 public Set<String> getMissingDictionaryFiles() { 210 return missingDictionaryFiles; 211 } 212 213 /** 214 * @return the invalidDictionaryFiles 215 */ 216 public Set<String> getInvalidDictionaryFiles() { 217 return invalidDictionaryFiles; 218 } 219 220 221 222 }