001 /*
002 * Copyright 2011 The Kuali Foundation
003 *
004 * Licensed under the Educational Community License, Version 1.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/ecl1.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 }