/*******************************************************************************
* Copyright 2014 JHC Systems Limited
*
* 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 jhc.redsniff.generation;
import java.io.File;
import java.io.FileWriter;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.filefilter.FileFilterUtils;
import org.apache.commons.io.filefilter.TrueFileFilter;
import org.hamcrest.generator.QDox;
import org.hamcrest.generator.QDoxFactoryReader;
import org.hamcrest.generator.QuickReferenceWriter;
import org.hamcrest.generator.SugarConfiguration;
import org.hamcrest.generator.SugarGenerator;
public class PackageScanningGenerator {
private final SugarConfiguration sugarConfiguration;
private final ClassLoader classLoader;
private final QDox qdox;
private File sourceDir;
private Class<?> parentClass;
public PackageScanningGenerator(SugarConfiguration sugarConfiguration,
ClassLoader classLoader,Class<?> parentClass) {
this.sugarConfiguration = sugarConfiguration;
this.classLoader = classLoader;
this.parentClass = parentClass;
qdox = new QDox();
}
public void addSourceDir(File sourceDir) {
this.sourceDir = sourceDir;
qdox.addSourceTree(sourceDir);
}
public void addClasses(String package_name_prefix) {
try {
for (String className : classesInPackage(package_name_prefix))
addClass(className);
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}
}
private Collection<String> classesInPackage(String package_name_prefix) {
File packageDir=new File(sourceDir.getAbsolutePath() +"\\"+ package_name_prefix.replaceAll("\\.","\\\\"));
Set<String> classNames = new HashSet<String>();
for(File classFile:FileUtils.listFiles(packageDir, FileFilterUtils.suffixFileFilter(".java"),TrueFileFilter.INSTANCE))
classNames.add(classFile.getAbsolutePath().replace(sourceDir.getAbsolutePath()+"\\","").replace(".java","").replaceAll("\\\\", "."));
//classNames.remove(o)
return classNames;
}
private void addClass(String className) throws ClassNotFoundException {
Class<?> cls = classLoader.loadClass(className);
sugarConfiguration.addFactoryMethods(new QDoxFactoryReader(
new FactoryMethodReader(cls,parentClass), qdox, className));
}
public static void main(String[] args) throws Exception {
if (args.length != 5) {
System.err
.println("Args: source-dir package-class-filter parent-class generated-class output-dir");
System.err.println("");
System.err
.println(" source-dir : Path to Java source containing matchers to generate sugar for.");
System.err
.println(" May contain multiple paths, separated by commas.");
System.err.println(" e.g. src/java,src/more-java");
System.err
.println(" package-class-filter : base of package to look for classes with methods, eg jhc.selenium.matchers");
System.err.println("");
System.err
.println("parent-class : Full name of parent class type to examine - eg org.hamcrest.Matcher, jhc.selenium.seeker.Seeker");
System.err
.println(" e.g. org.myproject.MyMatchers");
System.err
.println("generated-class : Full name of class to generate.");
System.err
.println(" e.g. org.myproject.MyMatchers");
System.err.println("");
System.err
.println(" output-dir : Where to output generated code (package subdirs will be");
System.err.println(" automatically created).");
System.err.println(" e.g. build/generated-code");
System.exit(-1);
}
String srcDirs = args[0];
String package_name_prefix = args[1];
String parentClassName= args[2];
String fullClassName = args[3];
File outputDir = new File(args[4]);
String fileName = fullClassName.replace('.', File.separatorChar)
+ ".java";
int dotIndex = fullClassName.lastIndexOf(".");
String packageName = dotIndex == -1 ? "" : fullClassName.substring(0,
dotIndex);
String shortClassName = fullClassName.substring(dotIndex + 1);
if (!outputDir.isDirectory()) {
System.err.println("Output directory not found : "
+ outputDir.getAbsolutePath());
System.exit(-1);
}
Class<?> parentClass = Class.forName(parentClassName);
File outputFile = new File(outputDir, fileName);
outputFile.getParentFile().mkdirs();
File tmpFile = new File(outputDir,fileName + ".tmp");
SugarGenerator sugarGenerator = new SugarGenerator();
try {
sugarGenerator.addWriter(new SeleniumFactoryWriter(packageName,
shortClassName, new FileWriter(tmpFile)));
sugarGenerator.addWriter(new QuickReferenceWriter(System.out));
PackageScanningGenerator pkgScanningGenerator = new PackageScanningGenerator(
sugarGenerator,
PackageScanningGenerator.class.getClassLoader(),parentClass );
if (srcDirs.trim().length() > 0) {
for (String srcDir : srcDirs.split(",")) {
pkgScanningGenerator.addSourceDir(new File(srcDir));
}
}
// could add use of xml just to list filter expressions
// pkgScanningGenerator.load(new InputSource(configFile));
pkgScanningGenerator.addClasses(package_name_prefix);
System.out.println("Generating " + fullClassName);
sugarGenerator.generate();
sugarGenerator.close();
outputFile.delete();
FileUtils.moveFile(tmpFile, outputFile);
} finally {
tmpFile.delete();
sugarGenerator.close();
}
}
}