package pt.ist.fenixframework.core;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import pt.ist.fenixframework.atomic.ProcessAtomicAnnotations;
import pt.ist.fenixframework.core.DmlFile;
import pt.ist.fenixframework.core.PostProcessDomainClasses;
import pt.ist.fenixframework.core.Project;
/**
* This class aggregates the whole post-processing required on the domain classes.
*/
public class FullPostProcessDomainClasses {
private static final Logger logger = LoggerFactory.getLogger(FullPostProcessDomainClasses.class);
private String projectName;
private File dir;
private void processArgs(String[] args) {
int i = 0;
while (i < args.length) {
if ("-cd".equals(args[i])) {
final String dirName = getNextArg(args, i);
dir = new File(dirName);
if (!dir.isDirectory()) {
String message = "Parameter -cd value '" + dirName + "' is not a directory.";
logger.error(message);
throw new Error(message);
}
consumeArg(args, i);
i += 2;
} else if ("-pn".equals(args[i])) {
projectName = getNextArg(args, i);
consumeArg(args, i);
i += 2;
} else if (args[i] != null) {
throw new Error("Unknown argument: '" + args[i] + "'");
} else {
i++;
}
}
}
private void consumeArg(String[] args, int i) {
args[i] = null;
}
private String getNextArg(String[] args, int i) {
int next = i + 1;
if ((next >= args.length) || (args[next] == null)) {
String message = "Invalid argument following '" + args[i] + "'";
logger.error(message);
throw new Error(message);
}
String result = args[next];
consumeArg(args, next);
return result;
}
/**
* Command-line API to start the full post-processing.
* @param args Expected values are:
*
* <ul>
*
* <li><code>-pn <projectName></code>: the name of the project being post-processed. This
* is used to locate the <code><projectName>/project.properties</code> file;</li>
* <li><code>-cd <classesDirectory></code>: single directory with the compiled classes.
* All classes here will be post-processed if required.</li>
*
* </ul>
*/
public static void main(String args[]) throws Exception {
FullPostProcessDomainClasses processor = new FullPostProcessDomainClasses();
processor.processArgs(args);
apply(processor.projectName, processor.dir, Thread.currentThread().getContextClassLoader());
}
/**
* Programmatic API to start the full post-processing.
*
* @param projectName the name of the project being post-processed. This is used to locate the
* <code><projectName>/project.properties</code> file
* @param classesDirectory single directory with the compiled classes. All classes here will be
* post-processed if required.
* @param parentClassLoader the class loader on which to delegate the loading of classes
*/
public static void apply(String projectName, File classesDirectory,
ClassLoader parentClassLoader) throws Exception {
injectCode(projectName, parentClassLoader);
ProcessAtomicAnnotations.processFile(classesDirectory);
}
/**
* Invoke the domain class post-processor.
*/
private static void injectCode(String projectName, ClassLoader parentClassLoader)
throws Exception {
List<URL> dmlFiles = new ArrayList<URL>();
for (DmlFile dmlFile : Project.fromName(projectName).getFullDmlSortedList()) {
dmlFiles.add(dmlFile.getUrl());
}
if (dmlFiles.isEmpty()) {
logger.warn("No dml files found to post process domain");
return;
}
PostProcessDomainClasses postProcessor =
new PostProcessDomainClasses(dmlFiles, parentClassLoader);
postProcessor.start();
}
}