View Javadoc

1   /**
2    * Copyright 2004-2013 The Kuali Foundation
3    *
4    * Licensed under the Educational Community License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    * http://www.opensource.org/licenses/ecl2.php
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.kuali.student.datadictionary.util;
17  
18  import java.io.File;
19  import java.io.FileNotFoundException;
20  import java.io.IOException;
21  import java.util.ArrayList;
22  import java.util.Collection;
23  import java.util.HashSet;
24  import java.util.LinkedHashMap;
25  import java.util.LinkedHashSet;
26  import java.util.List;
27  import java.util.Map;
28  import java.util.Set;
29  
30  import org.apache.commons.io.FileUtils;
31  import org.apache.commons.lang.exception.ExceptionUtils;
32  import org.kuali.rice.krad.datadictionary.DataObjectEntry;
33  import org.slf4j.Logger;
34  import org.slf4j.LoggerFactory;
35  import org.springframework.context.support.ClassPathXmlApplicationContext;
36  
37  public class DictionaryTesterHelper {
38  
39  	private static final Logger log = LoggerFactory.getLogger(DictionaryTesterHelper.class);
40  	
41  	private String outputDir;
42  	private Collection<String> inputFiles;
43  	private List<String> supportFiles;
44  	
45  	private Map<String, List<String>>inputFileToBeanNameMap = new LinkedHashMap<String, List<String>>();
46  
47  	private Set<String> missingDictionaryFiles;
48  
49  	private Set<String> invalidDictionaryFiles;
50  	
51  	
52  
53  	public DictionaryTesterHelper(String outputDir, Collection<String> inputFiles,
54  			List<String> supportFiles) {
55  		this.outputDir = outputDir;
56  		this.inputFiles = inputFiles;
57  		this.supportFiles = supportFiles;
58  	}
59  
60  	// public void loadApplicationContext() {
61  	// System.out.println
62  	// ("DictionaryTesterHelper: begin loading application context");
63  	//
64  	// ac = new PathValidatingClassPathXmlApplicationContext();
65  	//
66  	// for (String candidateConfigFile : this.configFiles) {
67  	// ac.addContextFile(candidateConfigFile);
68  	// }
69  	//
70  	// ac.buildApplicationContext();
71  	// System.out.println
72  	// ("DictionaryTesterHelper: end loading application context");
73  	// }
74  	//
75  	// public Map<String, DataObjectEntry> getDataObjectEntryBeans () {
76  	// return (Map<String, DataObjectEntry>)
77  	// ac.getBeansOfType(DataObjectEntry.class);
78  	// }
79  
80  	public void doTest(String projectVersion, String formattedDate) {
81  
82  		missingDictionaryFiles = new LinkedHashSet<String>();
83  		
84  		invalidDictionaryFiles = new LinkedHashSet<String>();
85  		
86  		for (String inputFile : inputFiles) {
87  
88  			List<String> contextFiles = new ArrayList<String>();
89  
90  			contextFiles.add(inputFile);
91  			contextFiles.addAll(supportFiles);
92  
93  			ClassPathXmlApplicationContext ac;
94  			try {
95  				log.info("Starting on inputFile: " + inputFile);
96  				
97  				ac = new ClassPathXmlApplicationContext(
98  						contextFiles.toArray(new String[0]));
99  			} 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 }