/**
* Copyright (C) 2010 Lowereast Software
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.mattinsler.guiceymongo.data.generator;
import com.mattinsler.guiceymongo.data.generator.parser.GuiceyDataLexer;
import com.mattinsler.guiceymongo.data.generator.parser.GuiceyDataParser;
import com.mattinsler.guiceymongo.data.generator.parser.TypeParser;
import com.mattinsler.guiceymongo.data.generator.type.UserType;
import de.hunsicker.jalopy.Jalopy;
import joptsimple.OptionParser;
import joptsimple.OptionSet;
import joptsimple.OptionSpec;
import org.antlr.runtime.ANTLRFileStream;
import org.antlr.runtime.CommonTokenStream;
import org.antlr.runtime.tree.CommonTree;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import java.io.File;
import java.io.FileWriter;
import java.io.StringWriter;
import java.util.Arrays;
import java.util.List;
public class GuiceyDataGenerator {
private void parseDirectory(File directory, TypeParser typeParser) {
for (File file : directory.listFiles()) {
if (file.isFile()) {
for (String extension : _fileExtensions) {
if (file.getName().endsWith(extension)) {
parseFile(file, typeParser);
}
}
} else {
parseDirectory(file, typeParser);
}
}
}
private void parseFile(File file, TypeParser typeParser) {
if (!file.exists()) {
System.err.println("File " + file.getPath() + " does not exist.");
return;
}
if (!file.canRead()) {
System.err.println("File " + file.getPath() + " cannot be read.");
return;
}
if (file.isDirectory()) {
parseDirectory(file, typeParser);
return; //Do not continue to parse as file
}
try {
GuiceyDataLexer lexer = new GuiceyDataLexer(new ANTLRFileStream(file.getAbsolutePath()));
CommonTokenStream tokens = new CommonTokenStream(lexer);
GuiceyDataParser parser = new GuiceyDataParser(tokens);
GuiceyDataParser.start_return ret = parser.start();
CommonTree tree = (CommonTree)ret.getTree();
typeParser.parse(tree);
} catch (Exception e) {
System.err.println("File " + file.getPath() + " has errors:");
System.err.print(e);
}
}
private String _outputPackage;
private String[] _fileExtensions;
private File _sourceDirectory;
private boolean _isQuiet;
private boolean _useCamelCaseKeys;
public void setSourceDirectory(String sourceDirectory) {
_sourceDirectory = new File(sourceDirectory);
}
public void setOutputPackage(String outputPackage) {
_outputPackage = outputPackage;
}
public void setFileExtensions(String... fileExtensions) {
_fileExtensions = fileExtensions;
}
public void setIsQuiet(boolean isQuiet) {
this._isQuiet = isQuiet;
}
public void setUseCamelCaseKeys(boolean useCamelCaseKeys) {
this._useCamelCaseKeys = useCamelCaseKeys;
}
public void generate(String... fileOrDirectoryNames) {
generate(Arrays.asList(fileOrDirectoryNames));
}
public void generate(List<String> pathNames) {
// just in case ...
Logger rootLogger = Logger.getRootLogger();
if (!rootLogger.getAllAppenders().hasMoreElements())
rootLogger.setLevel(Level.OFF);
TypeRegistry registry = new TypeRegistry();
TypeParser parser = new TypeParser(registry, _useCamelCaseKeys, _isQuiet);
TypeGenerator generator = new TypeGenerator(registry);
for (String pathName : pathNames) {
parseFile(new File(pathName), parser);
}
File outputDirFile = new File(_sourceDirectory, _outputPackage.replace('.', '/'));
outputDirFile.mkdirs();
Jalopy jalopy = new Jalopy();
for (UserType type : registry.getTypes(UserType.class)) {
if (type.getParentType() == null) {
File file = new File(outputDirFile, type.getJavaType() + ".java");
StringWriter stringWriter = new StringWriter();
try {
stringWriter.append("package ").append(_outputPackage).append(";\n\n");
generator.generate(stringWriter, type);
stringWriter.flush();
StringBuffer buffer = new StringBuffer();
jalopy.setInput(stringWriter.toString(), file.getPath());
jalopy.setOutput(buffer);
FileWriter writer = new FileWriter(file);
if (jalopy.format() && Jalopy.State.PARSED == jalopy.getState()) {
writer.write(buffer.toString());
} else {
writer.write(stringWriter.toString());
}
writer.close();
} catch (Exception e) {
System.err.println("Error in writing type " + type.getGuiceyType());
System.err.println(e);
try {
FileWriter writer = new FileWriter(file);
writer.write(stringWriter.toString());
writer.close();
} catch (Exception f) {
System.err.println("Yet another error in writing type " + type.getGuiceyType());
System.err.println(f);
}
}
}
}
}
public static void main(String[] args) {
OptionParser parser = new OptionParser();
OptionSpec<String> sourceDirectory = parser.acceptsAll(Arrays.asList("s", "src")).withRequiredArg().ofType(String.class).defaultsTo("src").describedAs("Output source directory");
OptionSpec<String> packageName = parser.acceptsAll(Arrays.asList("p", "package")).withRequiredArg().ofType(String.class).defaultsTo("data").describedAs("Package to put all generated classes into");
OptionSpec<Void> useCamelCase = parser.acceptsAll(Arrays.asList("c", "useCamelCase"), "Use camel case for mongo field names. By convention field names are specified as field_name, which will generate an object as {'field_name': true}. Using this option, {'fieldName': true} will be generated.");
OptionSpec<Void> isQuiet = parser.acceptsAll(Arrays.asList("q", "quiet"), "Do not print informational messages");
parser.acceptsAll(Arrays.asList("h", "help"), "Show help");
OptionSet options = parser.parse(args);
if (options.has("h") || options.nonOptionArguments().size() == 0) {
try {
System.out.println("Usage: [how you ran this] [options] file ...");
parser.printHelpOn(System.out);
} catch (Exception e) {
e.printStackTrace();
}
return;
}
GuiceyDataGenerator generator = new GuiceyDataGenerator();
generator.setOutputPackage(packageName.value(options));
generator.setSourceDirectory(sourceDirectory.value(options));
generator.setIsQuiet(options.has(isQuiet));
generator.setUseCamelCaseKeys(options.has(useCamelCase));
generator.generate(options.nonOptionArguments());
}
}