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 }