package com.smartgwt.sample.showcase.server;
import java.io.*;
import java.util.*;
import java.util.regex.*;
public class GenerateSourceFiles {
//--------------------------------------------------------------------------------------------------
private static final String[] ClassesToSkip = new String[] {"public static class Factory"};
private static final Pattern EndOfFieldPattern1 = Pattern.compile(".*; *");
private static final Pattern EndOfFieldPattern2 = Pattern.compile(".*;.*//.*");
private static final String[] FieldsToSkip = new String[] {"private static final String DESCRIPTION"};
private static final String[] LinesToSkip = new String[] {"package com.smartgwt",
"import com.smartgwt.sample.showcase.client.PanelFactory", "import com.smartgwt.sample.showcase.client.ShowcasePanel"
};
private static final String[] MethodsToSkip = new String[] {
"public String getIntro", "public String getSourceUrl" };
private static final Pattern ViewPanelReturnPattern = Pattern.compile("[ \t]*return.*");
// The _dataFileMap key is the class or data file name; the value is the path to the file
private static Map<String, String> _dataFileMap;
private static Map<String, Pattern> _dataFileRegexMap;
// The _dataFilePathsMap key is the class name; the value is the list of data files
private static Map<String, Set<String>> _dataFilePathsMap;
private static int _showcaseClientDirLength;
private static String _showcaseDir;
private static String _sourceOutputDir;
//--------------------------------------------------------------------------------------------------
private enum ESourceFileType {
DataSource("extends DataSource"),
Sample("public Canvas getViewPanel"),
Unknown("");
private String _containsString;
private ESourceFileType(final String containsString) {
_containsString = containsString;
} // ESourceFileType()
private static ESourceFileType lookup(final String line) {
ESourceFileType result = ESourceFileType.Unknown;
for (ESourceFileType sourceFileType : ESourceFileType.values()) {
if (line.contains(sourceFileType._containsString)) {
result = sourceFileType;
break;
}
}
return result;
} // lookup()
} // enum ESourceFileType
//--------------------------------------------------------------------------------------------------
private static void checkForDataFile(final String line, final String className) {
boolean matchFound = false;
Pattern p;
Matcher m;
for (Map.Entry<String, String> dataFileMapEntry : _dataFileMap.entrySet()) {
p = ((Pattern)_dataFileRegexMap.get(dataFileMapEntry.getKey()));
matchFound = p.matcher(line).find(0);
if (matchFound) {
Set<String> dataFilePathSet = _dataFilePathsMap.get(className);
if (dataFilePathSet == null) {
dataFilePathSet = new TreeSet<String>();
}
dataFilePathSet.add(dataFileMapEntry.getValue());
_dataFilePathsMap.put(className, dataFilePathSet);
break;
}
}
} // checkForDataFile()
//--------------------------------------------------------------------------------------------------
private static int checkSkipEntries(final List<String> sourceLineList, final int lineIndex) {
int result = lineIndex;
String line = sourceLineList.get(result);
boolean matchFound = false;
for (String methodToSkip : MethodsToSkip) {
matchFound = line.contains(methodToSkip);
if (matchFound) {
result = skipBlock(sourceLineList, lineIndex);
break;
}
}
for (String classToSkip : ClassesToSkip) {
matchFound = line.contains(classToSkip);
if (matchFound) {
result = skipBlock(sourceLineList, result);
break;
}
}
if (!matchFound) {
for (String fieldToSkip : FieldsToSkip) {
matchFound = line.contains(fieldToSkip);
if (matchFound) {
while (!EndOfFieldPattern1.matcher(line).matches() &&
!EndOfFieldPattern2.matcher(line).matches()) {
line = sourceLineList.get(++result);
}
++result;
break;
}
}
}
if (!matchFound) {
for (String lineToSkip : LinesToSkip) {
matchFound = line.contains(lineToSkip);
if (matchFound) {
++result;
break;
}
}
}
return result;
} // checkSkipEntries()
//--------------------------------------------------------------------------------------------------
private static PrintWriter createOutputHTMLFile(final String sourceFileDirName,
final String targetSourceFilePath) throws Exception {
PrintWriter result;
String targetDir;
targetDir = targetSourceFilePath.substring(0, targetSourceFilePath.lastIndexOf('/'));
new File(targetDir).mkdirs();
result = new PrintWriter(targetSourceFilePath);
writeStartOfHTMLFile(result, sourceFileDirName, targetSourceFilePath);
return result;
} // createOutputHTMLFile()
//--------------------------------------------------------------------------------------------------
private static void generateDataHTMLFile(final String sourceFilePath,
final String targetFilePath) {
String targetDir;
targetDir = targetFilePath.substring(0, targetFilePath.lastIndexOf('/'));
new File(targetDir).mkdirs();
try {
PrintWriter sourceWriter = createOutputHTMLFile(sourceFilePath, targetFilePath);
writeStartOfDataHTMLFile();
BufferedReader reader;
reader = new BufferedReader(new FileReader(sourceFilePath));
try {
String line;
do {
line = reader.readLine();
if (line != null) {
sourceWriter.println(line);
}
} while (line != null);
}
finally {
reader.close();
}
writeEndOfHTMLFile(sourceWriter);
sourceWriter.close();
}
catch (Exception e) {
System.err.println("Error creating data HTML file " + targetFilePath + " [" +
e.getMessage() + "]");
}
} // generateDataHTMLFile()
//--------------------------------------------------------------------------------------------------
private static void generateDataURLRecordsClass() {
try {
PrintWriter writer = new PrintWriter(_showcaseDir + "/DataURLRecords.java");
writer.println("package com.smartgwt.sample.showcase.client;");
writer.println("// This file is automatically generated. Do not modify it manually.");
writer.println("import java.util.TreeMap;");
writer.println("class DataURLRecords {");
writer.println("private static TreeMap<String, String[]> _dataURLsMap;");
writer.println("private static final DataURLRecord[] _dataURLRecords = new DataURLRecord[] {");
int dataFilePathsCount = 0;
for (Map.Entry<String, Set<String>> dataFilePathsEntry : _dataFilePathsMap.entrySet()) {
if (dataFilePathsCount > 0) writer.println(",");
writer.print("new DataURLRecord(\"" + dataFilePathsEntry.getKey() + "\",");
int pathCount = 0;
Set<String> pathsToAdd = new TreeSet<String>();
Set<String> pathsPossiblyToAdd = new TreeSet<String>(dataFilePathsEntry.getValue());
Set<String> tmpAddSet = new TreeSet<String>();
while (!pathsPossiblyToAdd.isEmpty()) {
Iterator<String> pathWriteIterator=pathsPossiblyToAdd.iterator();
while (pathWriteIterator.hasNext()) {
String dataFilePath=pathWriteIterator.next();
if (!pathsToAdd.contains(dataFilePath)) {
pathsToAdd.add(dataFilePath);
String className=new String(dataFilePath);
className = className.replaceAll("([^/]*/)*", "");
className = className.replaceAll("\\.java", "");
System.err.println(dataFilePathsEntry.getKey() + ": "+dataFilePath + "-->" + className);
Iterator<String> recursivePathIterator=null;
if (_dataFilePathsMap.containsKey(className))
recursivePathIterator=_dataFilePathsMap.get(className).iterator();
if (recursivePathIterator != null) while (recursivePathIterator.hasNext()) {
String newPath=recursivePathIterator.next();
if (!pathsToAdd.contains(newPath) && !tmpAddSet.contains(newPath))
tmpAddSet.add(newPath);
}
}
}
pathsPossiblyToAdd.clear();
pathsPossiblyToAdd.addAll(tmpAddSet);
tmpAddSet.clear();
}
Iterator<String> pathWriteIterator=pathsToAdd.iterator();
while (pathWriteIterator.hasNext()) {
String dataFilePath=pathWriteIterator.next();
writer.print(++pathCount == 1 ? "" : ",");
writer.print('"' + dataFilePath + '"');
}
writer.print(")");
++dataFilePathsCount;
}
writer.println("};");
writer.println("private static class DataURLRecord {");
writer.println("private String _className;");
writer.println("private String[] _urls;");
writer.println("private DataURLRecord(String className, String... urls) {");
writer.println(" _className = className;");
writer.println(" _urls = urls;");
writer.println("} // DataURLRecord()");
writer.println("} // class DataURLRecord");
writer.println("static String[] getDataURLs(final String className) {");
writer.println(" if (_dataURLsMap == null) {");
writer.println(" _dataURLsMap = new TreeMap<String, String[]>();");
writer.println(" for (DataURLRecord dataURLRecord : _dataURLRecords) {");
writer.println(" _dataURLsMap.put(dataURLRecord._className, dataURLRecord._urls);");
writer.println(" }");
writer.println(" }");
writer.println(" return _dataURLsMap.get(className);");
writer.println("} // getDataURLs()");
writer.println("}");
writer.close();
}
catch (Exception e) {
System.err.println("Error attempting to write data URL file (" + e.getMessage() + ")");
e.printStackTrace();
}
} // generateDataURLRecordsClass()
//--------------------------------------------------------------------------------------------------
private static void generateFile(final String sourceFileDirName, final String className) {
String sourceFilePath = sourceFileDirName + "/" + className + ".java";
String targetSourceFilePath = _sourceOutputDir +
sourceFileDirName.substring(_showcaseClientDirLength) + "/" +
className + ".java.html";
try {
List<String> sourceLineList = new ArrayList<String>();
ESourceFileType sourceFileType;
sourceFileType = loadFileIntoStringList(sourceFilePath, sourceLineList, className);
if (sourceFileDirName.endsWith("com/smartgwt/sample/showcase/client/data")) {
sourceFileType = ESourceFileType.DataSource;
}
switch (sourceFileType) {
case DataSource:
generateJavaDataHTMLFile(sourceFileDirName, sourceLineList, targetSourceFilePath);
break;
case Sample:
generateSampleHTMLFile(sourceFileDirName, className, sourceLineList, targetSourceFilePath);
break;
case Unknown:
break;
}
}
catch (Exception e) {
System.err.println("Error attempting to generate HTML for: " + sourceFilePath + " (" +
e.getMessage() + ")");
e.printStackTrace();
}
} // generateFile()
//--------------------------------------------------------------------------------------------------
private static void generateJavaDataHTMLFile(final String sourceFileDirName,
final List<String> sourceLineList,
final String targetSourceFilePath) throws Exception {
String targetDir;
targetDir = targetSourceFilePath.substring(0, targetSourceFilePath.lastIndexOf('/'));
new File(targetDir).mkdirs();
PrintWriter sourceWriter = createOutputHTMLFile(sourceFileDirName, targetSourceFilePath);
writeStartOfDataHTMLFile();
for (String line : sourceLineList) {
sourceWriter.println(line);
}
writeEndOfHTMLFile(sourceWriter);
sourceWriter.close();
} // generateJavaDataHTMLFile()
//--------------------------------------------------------------------------------------------------
private static void generateSampleHTMLFile(final String sourceFileDirName, final String className,
final List<String> sourceLineList,
final String targetSourceFilePath) throws Exception {
String prevLine = "";
boolean inComment = false;
PrintWriter sourceWriter = null;
for (int lineIndex = 0; lineIndex < sourceLineList.size();) {
String line = sourceLineList.get(lineIndex);
boolean generateOutput = true;
if (inComment) {
inComment = !line.contains("*/");
} else if (line.contains("/*")) {
inComment = true;
}
else if (line.contains(" extends ShowcasePanel")) {
// slip in EntryPoint import
line = "import com.google.gwt.core.client.EntryPoint;\n\n" +
"public class " + className + " implements EntryPoint {";
}
else if (line.contains("public Canvas getViewPanel")) {
lineIndex = outputGetViewPanel(sourceLineList, lineIndex, sourceWriter);
generateOutput = false;
}
else {
int oldLineIndex = lineIndex;
lineIndex = checkSkipEntries(sourceLineList, lineIndex);
generateOutput = lineIndex == oldLineIndex;
}
if (generateOutput) {
if (sourceWriter == null) {
sourceWriter = createOutputHTMLFile(sourceFileDirName, targetSourceFilePath);
writeStartOfSampleHTMLFile(sourceWriter);
}
if (line.length() > 0 || prevLine.length() > 0) {
sourceWriter.println(line);
prevLine = line;
}
++lineIndex;
}
}
if (sourceWriter != null) {
writeEndOfHTMLFile(sourceWriter);
sourceWriter.close();
}
} // generateSampleHTMLFile()
//--------------------------------------------------------------------------------------------------
private static Set<String> loadDataDirNames(final String... args) {
Set<String> result = new HashSet<String>();
result.add(_showcaseDir + "/../../../../../../war/data");
result.add(_showcaseDir + "/../../../../../../war/ds");
result.add(_showcaseDir + "/data");
for (int argIndex = 2; argIndex < args.length; ++argIndex) {
String dataDir = args[argIndex].replace("\\\\", "/").replace("\\", "/");
result.add(dataDir);
}
return result;
} // loadDataDirNames()
//--------------------------------------------------------------------------------------------------
private static void loadDataFileOrClassNames(final File fileOrDirectory) throws IOException {
if (fileOrDirectory.isDirectory()) {
if (!fileOrDirectory.getName().startsWith(".")) {
File[] files = fileOrDirectory.listFiles();
for (File directoryEntry : files) {
loadDataFileOrClassNames(directoryEntry);
}
}
}
else {
String fileName = fileOrDirectory.getName();
if (!fileName.endsWith(".class")) {
String fileOrClassName;
String fileOrClassPath = fileOrDirectory.getCanonicalPath().replace('\\', '/');
if (fileName.endsWith(".java")) {
fileOrClassName = fileName.substring(0, fileName.lastIndexOf('.'));
fileOrClassPath = fileOrClassPath.substring(_showcaseClientDirLength + 1);
}
else {
fileOrClassName = fileName;
int publicIndex = fileOrClassPath.indexOf("war");
fileOrClassPath = "data_files/" + fileOrClassPath.substring(publicIndex + 7);
generateDataHTMLFile(fileOrDirectory.getCanonicalPath().replace('\\', '/'),
_sourceOutputDir + "/" + fileOrClassPath + ".html");
}
_dataFileMap.put(fileOrClassName, fileOrClassPath);
_dataFileRegexMap.put(fileOrClassName,
Pattern.compile("[^a-zA-Z0-9_]" + fileOrClassName + "[^a-zA-Z0-9_]"));
}
}
} // loadDataFileOrClassNames()
//--------------------------------------------------------------------------------------------------
private static ESourceFileType loadFileIntoStringList(final String filePath,
final List<String> sourceLineList,
final String className) throws IOException {
ESourceFileType result = ESourceFileType.Unknown;
BufferedReader reader;
reader = new BufferedReader(new FileReader(filePath));
try {
String line;
do {
line = reader.readLine();
if (line != null) {
checkForDataFile(line, className);
sourceLineList.add(line);
if (result == ESourceFileType.Unknown) {
result = ESourceFileType.lookup(line);
}
}
} while (line != null);
}
finally {
reader.close();
}
return result;
} // loadFileIntoStringList()
//--------------------------------------------------------------------------------------------------
public static void main(final String... args) {
if (args.length < 2) {
System.err.println("The first parameter is the showcase client directory");
System.err.println(" (e.g., c:/Smart GWT/Showcase/com/smartgwt/sample/showcase/client)");
System.err.println("The second parameter is the source HTML root directory");
System.err.println(" (e.g., c:/Smart GWT/Showcase/com/smartgwt/sample/showcase/public/source)");
System.err.println("Subsequent parameters are directories that contain data or data source");
System.err.println(" files. The following files are automatically included:");
System.err.println(" .../com/smartgwt/sample/showcase/public/data");
System.err.println(" .../com/smartgwt/sample/showcase/public/ds");
System.err.println(" .../com/smartgwt/sample/showcase/client/data");
System.exit(0);
}
_showcaseDir = args[0].replace("\\\\", "/").replace("\\", "/");
_sourceOutputDir = args[1].replace("\\\\", "/").replace("\\", "/");
Set<String> dataDirNameSet = loadDataDirNames(args);
_showcaseClientDirLength = _showcaseDir.length();
_dataFileMap = new TreeMap<String, String>();
_dataFileRegexMap = new TreeMap<String, Pattern>();
_dataFilePathsMap = new TreeMap<String, Set<String>>();
try {
for (String dataDir : dataDirNameSet) {
loadDataFileOrClassNames(new File(dataDir));
}
processJavaFiles(new File(_showcaseDir));
generateDataURLRecordsClass();
}
catch (IOException ioe) {
System.err.println("Error processing showcase: " + ioe.getMessage());
}
} // main()
//--------------------------------------------------------------------------------------------------
private static void processJavaFiles(final File fileOrDirectory) throws IOException {
if (fileOrDirectory.isDirectory()) {
File[] files = fileOrDirectory.listFiles();
for (File directoryEntry : files) {
processJavaFiles(directoryEntry);
}
}
else if (fileOrDirectory.getName().endsWith(".java")) {
String filePath = fileOrDirectory.getPath().replace("\\\\", "/").replace("\\", "/");
int lastSlashIndex = filePath.lastIndexOf('/');
String directoryName = filePath.substring(0, lastSlashIndex);
String fileName = fileOrDirectory.getName();
String className = fileName.substring(0, fileName.lastIndexOf('.'));
generateFile(directoryName, className);
}
} // processJavaFiles()
//--------------------------------------------------------------------------------------------------
private static int outputGetViewPanel(final List<String> sourceLineList, final int lineIndex,
final PrintWriter sourceWriter) {
int result = lineIndex;
sourceWriter.println(" public void onModuleLoad() {");
while (sourceLineList.get(result).indexOf('{') < 0) {
++result;
}
++result;
boolean returnFound;
int openBraceCount = 1;
String line = sourceLineList.get(result);
do {
int openBracesOnLine = 0;
int braceIndex = 0;
while (line.indexOf('{', braceIndex) >= 0) {
++openBracesOnLine;
braceIndex = line.indexOf('{', braceIndex) + 1;
}
int closeBracesOnLine = 0;
braceIndex = 0;
while (line.indexOf('}', braceIndex) >= 0) {
++closeBracesOnLine;
braceIndex = line.indexOf('}', braceIndex) + 1;
}
openBraceCount += openBracesOnLine - closeBracesOnLine;
returnFound = openBraceCount == 1 && ViewPanelReturnPattern.matcher(line).matches();
if (!returnFound) {
sourceWriter.println(line);
line = sourceLineList.get(++result);
}
} while (!returnFound);
sourceWriter.println(line.replace("return ", "").replace(";", ".draw();"));
++result;
return result;
} // outputGetViewPanel()
//--------------------------------------------------------------------------------------------------
private static int skipBlock(final List<String> sourceLineList, final int lineIndex) {
int result = lineIndex;
String line = sourceLineList.get(result);
int openBraceCount = 0;
while (line.indexOf('{') < 0) {
line = sourceLineList.get(++result);
}
do {
int openBracesOnLine = 0;
int braceIndex = 0;
while (line.indexOf('{', braceIndex) >= 0) {
++openBracesOnLine;
braceIndex = line.indexOf('{', braceIndex) + 1;
}
int closeBracesOnLine = 0;
braceIndex = 0;
while (line.indexOf('}', braceIndex) >= 0) {
++closeBracesOnLine;
braceIndex = line.indexOf('}', braceIndex) + 1;
}
openBraceCount += openBracesOnLine - closeBracesOnLine;
if (openBraceCount > 0) {
line = sourceLineList.get(++result);
}
} while (openBraceCount > 0);
++result;
return result;
} // skipBlock()
//--------------------------------------------------------------------------------------------------
private static void writeEndOfHTMLFile(final PrintWriter sourceWriter) {
sourceWriter.println("</textarea>");
sourceWriter.println("<script class='javascript'>");
sourceWriter.println("dp.SyntaxHighlighter.HighlightAll(\"code\");");
sourceWriter.println("</script>");
sourceWriter.println("</body>");
sourceWriter.println("</html>");
} // writeEndOfHTMLFile()
//--------------------------------------------------------------------------------------------------
private static void writeStartOfDataHTMLFile() {
// nothing to write (currently)
} // writeStartOfDataHTMLFile()
//--------------------------------------------------------------------------------------------------
private static void writeStartOfHTMLFile(final PrintWriter sourceWriter,
final String sourceFileDirName, String targetSourceFilePath) {
int depth = 0;
if (sourceFileDirName.contains("/public/")) {
depth = sourceFileDirName.substring(sourceFileDirName.indexOf("/public/")).split("/").length - 1;
}
else if (sourceFileDirName.contains("/com/")) {
depth = sourceFileDirName.substring(sourceFileDirName.indexOf("/com/")).split("/").length - 5;
} else if (sourceFileDirName.contains("/war/")) {
depth = sourceFileDirName.substring(sourceFileDirName.indexOf("/war/")).split("/").length -2;
} else {
throw new RuntimeException("Unrecognized path " + sourceFileDirName);
}
String parentDirs = "";
for (int i = 0; i < depth; i++) {
parentDirs += "../";
}
sourceWriter.println("<html>");
sourceWriter.println("<head>");
sourceWriter.println("<link rel='stylesheet' href='" + parentDirs +
"js/sh/SyntaxHighlighter.css' type='text/css' />");
sourceWriter.println("<script src='" + parentDirs + "js/sh/shCore.js'></script>");
String type;
if(targetSourceFilePath.contains(".xml")) {
type= "xml";
} else if(targetSourceFilePath.contains(".css")) {
type= "css";
} else if (targetSourceFilePath.contains(".js")){
type= "js";
} else {
type= "java";
}
if(type.equals("xml")) {
sourceWriter.println("<script src='" + parentDirs + "js/sh/shBrushXml.js'></script>");
} else if(type.equals("css")) {
sourceWriter.println("<script src='" + parentDirs + "js/sh/shBrushCss.js'></script>");
} else if (type.equals("js")){
sourceWriter.println("<script src='" + parentDirs + "js/sh/shBrushJScript.js'></script>");
} else {
sourceWriter.println("<script src='" + parentDirs + "js/sh/shBrushJava.js'></script>");
}
sourceWriter.println("<style>");
sourceWriter.println("* {");
sourceWriter.println("font-family:Courier New,monospace;");
sourceWriter.println(" padding: 0;");
sourceWriter.println(" margin: 0;");
sourceWriter.println(" white-space: nowrap;");
sourceWriter.println(" font-size: 11px;");
sourceWriter.println("}");
sourceWriter.println(".dp-highlighter {");
sourceWriter.println(" white-space: nowrap;");
sourceWriter.println(" overflow: visible;");
sourceWriter.println(" width: 600px;");
sourceWriter.println(" font-size: 11px;");
sourceWriter.println(" font-family:Courier New,monospace;");
sourceWriter.println("}");
sourceWriter.println("</style>");
sourceWriter.println("</head>");
sourceWriter.println("<body>");
sourceWriter.println("<textarea name='code' class='" + type + ":nogutter' rows='15' cols='120'>");
} // writeStartOfHTMLFile()
//--------------------------------------------------------------------------------------------------
private static void writeStartOfSampleHTMLFile(final PrintWriter sourceWriter) {
sourceWriter.println("/*");
sourceWriter.println(" * Smart GWT (GWT for SmartClient)");
sourceWriter.println(" * Copyright 2008 and beyond, Isomorphic Software, Inc.");
sourceWriter.println(" *");
sourceWriter.println(" * Smart GWT is free software; you can redistribute it and/or modify it");
sourceWriter.println(" * under the terms of the GNU Lesser General Public License version 3");
sourceWriter.println(" * as published by the Free Software Foundation. Smart GWT is also");
sourceWriter.println(" * available under typical commercial license terms - see");
sourceWriter.println(" * http://smartclient.com/license");
sourceWriter.println(" *");
sourceWriter.println(" * This software is distributed in the hope that it will be useful,");
sourceWriter.println(" * but WITHOUT ANY WARRANTY; without even the implied warranty of");
sourceWriter.println(" * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU");
sourceWriter.println(" * Lesser General Public License for more details.");
sourceWriter.println(" */");
sourceWriter.println();
} // writeStartOfSampleHTMLFile()
//--------------------------------------------------------------------------------------------------
}