package org.nocket.gen.domain;
import gengui.domain.AbstractDomainReference;
import gengui.domain.DomainClassReference;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.lang.StringUtils;
import org.apache.wicket.MarkupContainer;
import org.nocket.gen.domain.NocketGenerator.GenerationContext.FileData;
import org.nocket.gen.domain.ref.DomainClassReferenceFactory;
import org.nocket.gen.domain.ref.DomainReferenceFactoryI;
import org.nocket.gen.domain.visitor.DomainElementVisitorI;
import org.nocket.gen.domain.visitor.NocketGenerationVisitor;
import org.nocket.util.ArgReader;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class NocketGenerator {
final private static Logger log = LoggerFactory.getLogger(NocketGenerator.class);
public static class GenerationProcessDMDWebGenContext<E extends AbstractDomainReference> extends DMDWebGenContext<E> {
private final GenerationContext generationContext;
@SuppressWarnings({ "rawtypes", "unchecked" })
public GenerationProcessDMDWebGenContext(Boolean generatePanel, String srcDir, String genDir,
DomainReferenceFactoryI refFactory, GenerationContext generationContext) {
super(generatePanel, srcDir, genDir, refFactory);
this.generationContext = generationContext;
}
public GenerationContext getGenerationContext() {
return generationContext;
}
}
public static class GenerationContext {
List<FileData> fileDataList = new ArrayList<NocketGenerator.GenerationContext.FileData>();
class FileData {
String fileName;
boolean changed;
String error;
boolean newFile;
public FileData(String fileName, boolean newFile, boolean changed, String error) {
this.fileName = fileName;
this.newFile = newFile;
this.changed = changed;
this.error = error;
}
}
public void addFileData(String fileName, boolean newFile, boolean changed, String error) {
fileDataList.add(new FileData(fileName, newFile, changed, error));
}
public boolean hasErrors() {
for (FileData element : fileDataList) {
if (StringUtils.isNotBlank(element.error)) {
return true;
}
}
return false;
}
}
public void run(String[] args) {
String sourceDir = null;
String genDir = null;
Boolean generatePanel = false;
char option = ArgReader.ARGEND;
ArgReader argReader = new ArgReader(args, "t:s:g:y:h");
do {
try {
switch (option = argReader.getArg()) {
case 'h':
printHelp();
break;
case 's':
sourceDir = argReader.getArgValue().trim();
break;
case 'g':
genDir = argReader.getArgValue().trim();
break;
case 't':
generatePanel = argReader.getArgValue().trim().equalsIgnoreCase("panel");
break;
}
} catch (IllegalArgumentException ax) {
System.err.println(ax.getMessage());
printHelp();
return;
}
} while (option != ArgReader.ARGEND);
if (argReader.getPendingArgs().length == 0) {
System.err.println("Illegal arguments");
printHelp();
return;
}
//
new WebDomainProperties().init();
GenerationContext generationContext = new GenerationContext();
for (String clazz : argReader.getPendingArgs()) {
try {
Class<?> domainClass = Class.forName(clazz);
if (MarkupContainer.class.isAssignableFrom(domainClass)) {
log.error("Ignoring: " + clazz + "! It is a MarkupContainer not a Pojo!");
continue;
}
generateHTML(domainClass, generatePanel, sourceDir, genDir, generationContext);
} catch (Throwable e) {
if (log.isErrorEnabled()) {
log.error(e.getMessage(), e);
} else {
e.printStackTrace();
}
}
}
printStatistic(generationContext);
if (generationContext.hasErrors()) {
// if an error occured, set exit code to -1
System.exit(-1);
}
}
private void printStatistic(GenerationContext generationContext) {
StringBuilder builder = new StringBuilder("Generation statistic:\r\n");
builder.append("jfd.retention.strategy=").append(new WebDomainProperties().getJFDRetentionStrategy()).append("\r\n");
if (generationContext.fileDataList.isEmpty()) {
builder.append("No files processed.");
log.info(builder.toString());
return;
}
int changed = 0;
int unchanged = 0;
int errorCount = 0;
int newFiles = 0;
StringBuilder errorBuilder = new StringBuilder("The following errors occured during generation process:\r\n");
for (FileData filedata : generationContext.fileDataList) {
if (StringUtils.isNotBlank(filedata.error)) {
errorCount++;
errorBuilder.append(filedata.error).append("\r\n");
} else {
changed += filedata.changed ? 1 : 0;
unchanged += filedata.changed ? 0 : 1;
newFiles += filedata.newFile ? 1 : 0;
}
}
builder.append("Number of new files: " + newFiles + "\r\n");
builder.append("Number of changed files: " + changed + "\r\n");
builder.append("Number of unchanged files: " + unchanged + "\r\n");
builder.append("Number of files with error: " + errorCount + "\r\n");
if (errorCount > 0) {
builder.append(errorBuilder);
}
if (log.isInfoEnabled()) {
log.info(builder.toString());
} else {
System.out.println(builder.toString());
}
}
public void generateHTML(Class<?> domainClass, Boolean generatePanel, String sourceDir, String genDir,
GenerationContext generationContext) {
DomainClassReferenceFactory refFactory = new DomainClassReferenceFactory(domainClass, false);
DMDWebGenContext<DomainClassReference> context;
if (generationContext != null) {
// If there is a need for some statistic, an the specialized
// DMDWebGenContext will be used
context = new GenerationProcessDMDWebGenContext<DomainClassReference>(generatePanel, sourceDir, genDir,
refFactory, generationContext);
} else {
context = new DMDWebGenContext<DomainClassReference>(generatePanel, sourceDir, genDir, refFactory);
}
new DomainProcessor<DomainClassReference>(context, new MultiPassStrategy<DomainClassReference>() {
@Override
public DomainElementVisitorI<DomainClassReference> createVisitor(DMDWebGenContext<DomainClassReference> _dmdWebGenContext) {
return new NocketGenerationVisitor<DomainClassReference>(_dmdWebGenContext);
}
}).process();
}
private static void printHelp() {
System.err.println("Usage:\tjava " + NocketGenerator.class.getName()
+ " -s <SRC_DIR> -g <GEN_DIR> [-t (page | panel)] [-l <CSS_FILE>]* <JAVA_CLASS_1> (<JAVA_CLASS_2> ... <JAVA_CLASS_n>)");
System.err.println("Params:\t-s\tThe directory where HTML-Output will be written into package specific directories. Usually the \"src\" directory of the project.");
System.err.println("\t-g\tThe directory where Constants-Class-Output will be written into package specific directories. Usually the \"gen\" directory of the project.");
System.err.println("\t-t\tThe type of HTML artefact to create. By default, the generator tries to derive the type from existing Page/Panel classes. Pages are the fallback.");
System.err.println("\t-y\tSpecifies the kind of mask layouting the generated HTML is prepared for.");
System.err.println("\t...\tFQDN to java classes for which the html should be generated. The classes have to be in the classpath. Usually something like \"some.package.SomeType\".");
System.err.println("Help:\tThis tool loads the given java classes and uses reflection to parse them in order to create html output for them.");
System.err.println("\tThe output files are generated into the package folder of the given java class.");
System.err.println("\tFiles that are written to SRC_DIR are merged with fields that have been added to the specific java class.");
System.err.println("\tFiles that are written to GEN_DIR are always overwritten if they already exist.");
}
public static void main(String[] args) {
new NocketGenerator().run(args);
}
}