package net.jangaroo.jooc.backend;
import net.jangaroo.jooc.Jooc;
import net.jangaroo.jooc.JsWriter;
import net.jangaroo.jooc.ast.CompilationUnit;
import net.jangaroo.jooc.ast.IdeDeclaration;
import net.jangaroo.jooc.ast.PackageDeclaration;
import net.jangaroo.jooc.config.JoocOptions;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
/**
* Compilation unit sink factory for one compilation unit per output file.
*/
public class SingleFileCompilationUnitSinkFactory extends AbstractCompilationUnitSinkFactory {
private String suffix;
private boolean generateApi;
public SingleFileCompilationUnitSinkFactory(JoocOptions options, File destinationDir, boolean generateApi, String suffix) {
super(options, destinationDir);
this.suffix = suffix;
this.generateApi = generateApi;
}
protected File getOutputFile(File sourceFile, String[] packageName) {
return new File(getOutputFileName(sourceFile, packageName));
}
protected String getOutputFileName(File sourceFile, String[] packageName) {
String result;
if (getOutputDir() == null) {
result = sourceFile.getAbsoluteFile().getParentFile().getAbsolutePath();
} else {
result = getOutputDir().getAbsolutePath();
StringBuilder buffy = new StringBuilder(result);
for (String aPackageName : packageName) {
buffy.append(File.separator);
buffy.append(aPackageName);
}
result = buffy.toString();
}
result += File.separator;
result += sourceFile.getName();
int dotpos = result.lastIndexOf('.');
if (dotpos >= 0) {
result = result.substring(0, dotpos);
}
result += suffix;
return result;
}
public CompilationUnitSink createSink(PackageDeclaration packageDeclaration,
IdeDeclaration primaryDeclaration, File sourceFile,
final boolean verbose) {
final File outFile = getOutputFile(sourceFile, packageDeclaration.getQualifiedName());
String fileName = outFile.getName();
String classPart = fileName.substring(0, fileName.lastIndexOf('.'));
String className = primaryDeclaration.getName();
if (!classPart.equals(className)) {
Jooc.warning(primaryDeclaration.getSymbol(),
"class name should be equal to file name: expected " + classPart + ", found " + className);
}
createOutputDirs(outFile);
return new CompilationUnitSink() {
public File writeOutput(CompilationUnit compilationUnit) {
if (verbose) {
System.out.println("writing file: '" + outFile.getAbsolutePath() + "'"); // NOSONAR this is a cmd line tool
}
try {
OutputStreamWriter writer = new OutputStreamWriter(new FileOutputStream(outFile), "UTF-8");
try {
if (generateApi) {
ApiModelGenerator apiModelGenerator = new ApiModelGenerator(isExcludeClassByDefault(getOptions()));
apiModelGenerator.generateModel(compilationUnit).visit(new ActionScriptCodeGeneratingModelVisitor(writer));
} else {
JsWriter out = new JsWriter(writer);
try {
out.setOptions(getOptions());
compilationUnit.visit(new JsCodeGenerator(out));
} finally {
out.close();
}
}
} catch (IOException e) {
//noinspection ResultOfMethodCallIgnored
outFile.delete(); // NOSONAR
throw Jooc.error("error writing file: '" + outFile.getAbsolutePath() + "'", outFile, e);
}
} catch (IOException e) {
throw Jooc.error("cannot open output file for writing: '" + outFile.getAbsolutePath() + "'", outFile, e);
}
return outFile;
}
};
}
private static boolean isExcludeClassByDefault(JoocOptions options) {
try {
return options.isExcludeClassByDefault();
} catch (IncompatibleClassChangeError e) {
// ignore, old front ends did not know that you can exclude classes by default
return false;
}
}
}