1   
2   
3   
4   
5   
6   
7   
8   
9   
10  
11  
12  
13  
14  
15  
16  package org.kuali.student.datadictionary.mojo;
17  
18  import java.io.File;
19  import java.io.FileNotFoundException;
20  import java.io.FileOutputStream;
21  import java.io.OutputStream;
22  import java.io.PrintStream;
23  import java.net.MalformedURLException;
24  import java.net.URL;
25  import java.net.URLClassLoader;
26  import java.util.ArrayList;
27  import java.util.Collection;
28  import java.util.Iterator;
29  import java.util.LinkedHashMap;
30  import java.util.LinkedHashSet;
31  import java.util.List;
32  import java.util.Map;
33  import java.util.Set;
34  
35  import org.apache.maven.artifact.DependencyResolutionRequiredException;
36  import org.apache.maven.plugin.AbstractMojo;
37  import org.apache.maven.plugin.MojoExecutionException;
38  import org.apache.maven.project.MavenProject;
39  import org.joda.time.DateTime;
40  import org.kuali.student.common.mojo.AbstractKSMojo;
41  import org.kuali.student.contract.model.MessageStructure;
42  import org.kuali.student.contract.model.Service;
43  import org.kuali.student.contract.model.ServiceContractModel;
44  import org.kuali.student.contract.model.impl.ServiceContractModelCache;
45  import org.kuali.student.contract.model.impl.ServiceContractModelQDoxLoader;
46  import org.kuali.student.contract.model.util.DateUtility;
47  import org.kuali.student.contract.model.util.VersionLinesUtility;
48  import org.kuali.student.contract.model.validation.ServiceContractModelValidator;
49  import org.kuali.student.datadictionary.util.DictionaryFormatter;
50  import org.kuali.student.datadictionary.util.DictionaryTesterHelper;
51  import org.slf4j.Logger;
52  import org.slf4j.LoggerFactory;
53  
54  
55  
56  
57  
58  
59  
60  
61  
62  
63  
64  
65  
66  
67  
68  
69  
70  
71  
72  
73  
74  
75  
76  
77  
78  
79  
80  
81  
82  
83  
84  
85  
86  
87  public class KSDictionaryDocMojo extends AbstractKSMojo {
88  
89  	private static final Logger log = LoggerFactory.getLogger(KSDictionaryDocMojo.class);
90  	
91      
92  
93  
94  
95  
96      private MavenProject project;
97      
98     
99      
100     
101 
102 
103 
104     private List<String> supportFiles = new ArrayList<String>();
105     
106 
107 
108     private File htmlDirectory;
109 
110 	private String testDictionaryFile;
111 
112 	private LinkedHashMap<String, String> dictionaryFileToMessageStructureMap  = new LinkedHashMap<String, String>();
113    
114 	public void setHtmlDirectory(File htmlDirectory) {
115         this.htmlDirectory = htmlDirectory;
116     }
117 
118     public File getHtmlDirectory() {
119         return htmlDirectory;
120     }
121 
122     public MavenProject getProject() {
123         return project;
124     }
125 
126     public List<String> getSupportFiles() {
127         return supportFiles;
128     }
129 
130     public void setSupportFiles(List<String> supportFiles) {
131     	this.supportFiles.clear();
132     	
133     	if (supportFiles != null)
134     		this.supportFiles.addAll(supportFiles);
135     }
136     
137     @Override
138     public void execute()
139             throws MojoExecutionException {
140     	this.getLog().info("generating dictionary documentation");
141         
142         if (getPluginContext() != null) {
143         	project = (MavenProject) getPluginContext().get("project");
144         }
145         
146         
147         
148         
149         if (project != null) {
150             this.getLog().info("adding current project's classpath to plugin class loader");
151             List<String> runtimeClasspathElements;
152             try {
153                 runtimeClasspathElements = project.getRuntimeClasspathElements();
154             } catch (DependencyResolutionRequiredException ex) {
155                 throw new MojoExecutionException("Failed to get runtime classpath elements.", ex);
156             }
157             URL[] runtimeUrls = new URL[runtimeClasspathElements.size()];
158             for (int i = 0; i < runtimeClasspathElements.size(); i++) {
159                 String element = (String) runtimeClasspathElements.get(i);
160                 try {
161                     runtimeUrls[i] = new File(element).toURI().toURL();
162                 } catch (MalformedURLException ex) {
163                     throw new MojoExecutionException(element, ex);
164                 }
165             }
166             URLClassLoader newLoader = new URLClassLoader(runtimeUrls,
167                     Thread.currentThread().getContextClassLoader());
168             Thread.currentThread().setContextClassLoader(newLoader);
169         }
170 
171 
172         if (!htmlDirectory.exists()) {
173             if (!htmlDirectory.mkdirs()) {
174                 throw new IllegalArgumentException("Could not create directory "
175                         + this.htmlDirectory.getPath());
176             }
177         }
178         
179         Set<String> inpFiles = new LinkedHashSet<String>();
180 		if (project != null) {
181 			ServiceContractModel model = this.getModel();
182 			this.validate(model);
183 			inpFiles.addAll(extractDictionaryFiles(model));
184 
185 		} else {
186 			inpFiles.add(this.testDictionaryFile);
187 		}
188     
189 
190         String outputDir = this.htmlDirectory.getAbsolutePath();
191         DictionaryTesterHelper tester = new DictionaryTesterHelper(outputDir, inpFiles, this.supportFiles);
192         tester.doTest(project.getVersion(), DateUtility.asYMDHMInEasternTimeZone(new DateTime()));
193 
194         
195         String indexFileName = this.htmlDirectory.getPath() + "/" + "index.html";
196         File indexFile = new File(indexFileName);
197         OutputStream outputStream;
198         try {
199             outputStream = new FileOutputStream(indexFile, false);
200         } catch (FileNotFoundException ex) {
201 
202             throw new IllegalArgumentException(indexFileName, ex);
203         }
204         
205         String formattedDate = DateUtility.asYMDHMInEasternTimeZone(new DateTime());
206         
207         PrintStream out = new PrintStream(outputStream);
208         
209         DictionaryFormatter.writeHeader(out, "Data Dictionary Index");
210         
211         VersionLinesUtility.writeVersionTag(out, "<a href=\"index.html\">Home</a>", "<a href=\"../contractdocs/index.html\">Contract Docs Home</a>", project.getVersion(), formattedDate);
212         
213         out.println("<h1>Data Dictionary Index</h1>");
214         out.println("<blockquote>A Red background indicates that there is a problem with the data dictionary for that type.</blockquote>");
215         out.println("<ul>");
216         
217         Map<String, List<String>> fileToBeanNameMap = tester.getInputFileToBeanNameMap();
218         
219 		for (String inputFile : fileToBeanNameMap.keySet()) {
220 
221 			boolean containsError = false;
222 			
223 			if (tester.getInvalidDictionaryFiles().contains(inputFile)) {
224 				containsError = true;
225 			}
226 			
227 			List<String> beanIds = fileToBeanNameMap.get(inputFile);
228 
229 			for (String beanId : beanIds) {
230 
231 				String outputFileName = beanId + ".html";
232 				
233 				if (containsError)
234 					out.println ("<li class=\"invalid\">");
235 				else
236 					out.println ("<li>");
237 				
238 				out.println("<a href=\"" + outputFileName + "\">" + beanId
239 						+ "</a>");
240 			}
241 		}
242         out.println("</ul>");
243         
244 		
245         
246 		if (tester.getMissingDictionaryFiles().size() > 0) {
247 			out.println("<h1>Missing Dictionary Files</h1>");
248 			out.println("<blockquote>The Message structure exists but there is no dictionary file present.</blockquote>");
249 			out.println("<ul>");
250 			for (String missingFile : tester.getMissingDictionaryFiles()) {
251 				out.println("<li><b>" + missingFile + "</b></li>");
252 			}
253 			out.println("</ul>");
254 
255 		}
256         
257         DictionaryFormatter.writeFooter(out);
258         out.flush();
259         out.close();
260         
261         log.info("finished generating dictionary documentation");
262     }
263 
264 	private Collection<String> extractDictionaryFiles(
265 			ServiceContractModel model) {
266 		
267 		Set<String> dictionaryFiles = new LinkedHashSet<String>();
268 		
269 		List<MessageStructure> mss = new ArrayList<MessageStructure>(model.getMessageStructures());
270 		
271 		
272 		
273 		Set<String>mergedMessageStructureNames = new LinkedHashSet<String>();
274         
275         Iterator<MessageStructure> it = mss.iterator();
276         
277         while (it.hasNext()) {
278         	MessageStructure ms = it.next();
279 			
280         	String messageStructureName = ms.getXmlObject();
281         	
282         	if (mergedMessageStructureNames.contains(messageStructureName) || !messageStructureName.endsWith("Info")) {
283         		
284         		
285         		
286         		it.remove();
287         		
288         	}
289         	else
290         		mergedMessageStructureNames.add(ms.getName());
291 		}
292 		
293 		for (MessageStructure messageStructure : mss) {
294 			
295 			String inputFileName = "ks-" + messageStructure.getXmlObject() + "-dictionary.xml";
296 
297 			dictionaryFiles.add(inputFileName);
298 			
299 			
300 			dictionaryFileToMessageStructureMap.put(inputFileName, messageStructure.getXmlObject());
301 			
302 		}
303 		
304 		
305 		return dictionaryFiles;
306 	}
307 
308 	
309 
310 
311 
312 	public void setTestDictionaryFile(String dictionaryFile) {
313 		this.testDictionaryFile = dictionaryFile;
314 		
315 	}
316 }