package ecologylab.bigsemantics.compiler;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import ecologylab.bigsemantics.FileUtils;
import ecologylab.bigsemantics.collecting.MetaMetadataRepositoryLocator;
import ecologylab.bigsemantics.metadata.MetadataClassDescriptor;
import ecologylab.bigsemantics.metametadata.Build;
import ecologylab.bigsemantics.metametadata.FileTools;
import ecologylab.bigsemantics.metametadata.MetaMetadata;
import ecologylab.bigsemantics.metametadata.MetaMetadataRepository;
import ecologylab.bigsemantics.metametadata.RepositoryOrderingByGeneration;
import ecologylab.bigsemantics.namesandnums.SemanticsNames;
import ecologylab.generic.Debug;
import ecologylab.serialization.ClassDescriptor;
import ecologylab.serialization.SIMPLTranslationException;
import ecologylab.serialization.SimplTypesScope;
import ecologylab.serialization.SimplTypesScope.GRAPH_SWITCH;
import ecologylab.serialization.formatenums.Format;
import ecologylab.serialization.formatenums.StringFormat;
import ecologylab.translators.CodeTranslationException;
import ecologylab.translators.CodeTranslator;
/**
*
* @author quyin
*
*/
public class MetaMetadataCompiler extends Debug // ApplicationEnvironment
{
public static final String BUILTINS_CLASS_PACKAGE = ".builtins";
public static final String DECLARATION_CLASS_PACKAGE = ".declarations";
public static final String DECLARATION_CLASS_SUFFIX = "Declaration";
private static final String META_METADATA_COMPILER_TSCOPE_NAME = "meta-metadata-compiler-tscope";
private static final String META_METADATA_COMPILER_BUILTIN_DECLARATIONS_SCOPE = "meta-metadata-compiler-builtin-declarations-scope";
public void compile(CompilerConfig config) throws IOException, SIMPLTranslationException,
CodeTranslationException
{
debug("\n\n loading repository ...\n\n");
SimplTypesScope.enableGraphSerialization();
MetaMetadataRepository.initializeTypes();
MetaMetadataRepository repository = config.loadRepository();
SimplTypesScope tscope = repository.traverseAndGenerateTranslationScope(META_METADATA_COMPILER_TSCOPE_NAME);
CodeTranslator codeTranslator = config.getCompiler();
File generatedSemanticsLocation = config.getGeneratedSemanticsLocation();
File libraryDir = new File(generatedSemanticsLocation, "Library");
if (libraryDir.exists() && libraryDir.isDirectory())
{
FileUtils.deleteDir(libraryDir);
}
// generate declaration classes and scope
SimplTypesScope builtinDeclarationsScope = SimplTypesScope.get(META_METADATA_COMPILER_BUILTIN_DECLARATIONS_SCOPE, new Class[] {});
String builtinPackage = null;
for (ClassDescriptor mdCD : tscope.getClassDescriptors())
{
MetaMetadata definingMmd = ((MetadataClassDescriptor) mdCD).getDefiningMmd();
if (definingMmd.isBuiltIn())
{
ClassDescriptor declCD = (ClassDescriptor) mdCD.clone();
String packageName = mdCD.getDescribedClassPackageName();
String classSimpleName = mdCD.getDescribedClassSimpleName();
if (definingMmd.isRootMetaMetadata())
{
packageName += BUILTINS_CLASS_PACKAGE + DECLARATION_CLASS_PACKAGE;
classSimpleName += DECLARATION_CLASS_SUFFIX;
}
else
{
builtinPackage = packageName; // essentially, the old package name
packageName = packageName.replace(BUILTINS_CLASS_PACKAGE, BUILTINS_CLASS_PACKAGE + DECLARATION_CLASS_PACKAGE);
classSimpleName += DECLARATION_CLASS_SUFFIX;
}
declCD.setDescribedClassPackageName(packageName);
declCD.setDescribedClassSimpleName(classSimpleName);
builtinDeclarationsScope.addTranslation(declCD);
}
}
// compiler.translate(cd, config.getGeneratedBuiltinDeclarationsLocation(), config,
// newPackageName, newSimpleName, GenerateAbstractClass.TRUE);
CompilerConfig newConfig = (CompilerConfig) config.clone();
newConfig.setLibraryTScopeClassPackage("ecologylab.bigsemantics.metadata.builtins.declarations");
newConfig.setLibraryTScopeClassSimpleName("MetadataBuiltinDeclarationsTranslationScope");
// newConfig.setGenerateAbstractClass(true);
newConfig.setBuiltinDeclarationScopeName(SemanticsNames.REPOSITORY_BUILTIN_DECLARATIONS_TYPE_SCOPE);
newConfig.getClassesExcludedFromGeneratedTScopeClass()
.add("ecologylab.bigsemantics.metadata.builtins.InformationComposition");
ClassDescriptor infoCompCD = builtinDeclarationsScope.getClassDescriptorBySimpleName("InformationCompositionDeclaration");
codeTranslator.excludeClassFromTranslation(infoCompCD);
if (config.getGeneratedBuiltinDeclarationsLocation() != null)
codeTranslator.translate(config.getGeneratedBuiltinDeclarationsLocation(), builtinDeclarationsScope, newConfig);
// generate normal metadata classes
for (ClassDescriptor mdCD : tscope.getClassDescriptors())
{
MetaMetadata definingMmd = ((MetadataClassDescriptor) mdCD).getDefiningMmd();
if (definingMmd.isBuiltIn())
codeTranslator.excludeClassFromTranslation(mdCD);
}
debug("\n\n compiling to " + generatedSemanticsLocation + " ...\n\n");
codeTranslator.translate(generatedSemanticsLocation, tscope, config);
// generate repository build info:
generateRepositoryBuildInfo(config);
repository.build().copyFrom(this.build);
// generate repository file list:
generateRepositoryFileList(config);
// serialize post-inheritance repository files:
serializePostInheritanceRepository(config.getRepositoryLocation(), repository);
debug("\n\n compiler finished.");
}
static private String REPOSITORY_FILES_LST = "repositoryFiles.lst";
static private String REPOSITORY_BUILD_FILE = "buildInfo.xml";
private Build build;
public void generateRepositoryBuildInfo(CompilerConfig config)
{
File repositoryLocation = config.getRepositoryLocation();
assert repositoryLocation != null;
assert repositoryLocation.exists();
assert repositoryLocation.isDirectory();
debug("Repository location: " + repositoryLocation);
MetaMetadataRepository repoBuild = new MetaMetadataRepository();
build = repoBuild.build();
build.date = new Date();
try
{
build.host = InetAddress.getLocalHost().getHostName();
}
catch (UnknownHostException e1)
{
build.host = "<unable to get host name>";
e1.printStackTrace();
}
build.user = System.getProperty("user.name");
File repoBuildFile = new File(repositoryLocation, REPOSITORY_BUILD_FILE);
try
{
SimplTypesScope.serialize(repoBuild, repoBuildFile, Format.XML);
}
catch (SIMPLTranslationException e2)
{
error("Error saving build info!");
e2.printStackTrace();
}
}
public void generateRepositoryFileList(CompilerConfig config)
{
File repositoryLocation = config.getRepositoryLocation();
assert repositoryLocation != null;
assert repositoryLocation.exists();
assert repositoryLocation.isDirectory();
debug("Repository location: " + repositoryLocation);
List<String> items = getRepositoryFileItems(repositoryLocation, config.getRepositoryFormat());
File repoFilesLst = new File(repositoryLocation, REPOSITORY_FILES_LST);
PrintWriter pw;
try
{
pw = new PrintWriter(repoFilesLst);
for (String item : items)
{
debug(" Repository file: " + item);
pw.println(item);
}
pw.close();
}
catch (FileNotFoundException e)
{
error("Cannot write to " + repoFilesLst);
}
}
private List<String> getRepositoryFileItems(File repositoryLocation, Format repositoryFormat)
{
String repositoryPath = repositoryLocation.getAbsolutePath();
List<File> files = MetaMetadataRepositoryLocator.listRepositoryFiles(repositoryLocation,
repositoryFormat);
List<String> items = new ArrayList<String>();
for (File file : files)
{
String item = FileTools.getRelativePath(repositoryPath, file.getAbsolutePath());
item = item.replace('\\', '/'); // when specifying java resources use '/'
debug(" Repository files list item: " + item);
items.add(item);
}
return items;
}
static private String POST_INHERITANCE_REPOSITORY_DIR = "PostInheritanceRepository";
static private String POST_INHERITANCE_REPOSITORY_FILE_NAME = "post-inheritance-repository";
public static void serializePostInheritanceRepository(File repositoryLocation, MetaMetadataRepository repository)
{
assert repositoryLocation != null;
assert repositoryLocation.exists();
assert repositoryLocation.isDirectory();
Debug.debugT(MetaMetadataCompiler.class, "Repository location: " + repositoryLocation);
File postInheritanceRepositoryDir = new File(repositoryLocation.getParentFile(),
POST_INHERITANCE_REPOSITORY_DIR);
File xmlPostInheritanceRepositoryFile = null;
File jsonPostInheritanceRepositoryFile = null;
if (postInheritanceRepositoryDir.exists() && postInheritanceRepositoryDir.isDirectory())
{
xmlPostInheritanceRepositoryFile = new File(postInheritanceRepositoryDir,
POST_INHERITANCE_REPOSITORY_FILE_NAME + ".xml");
jsonPostInheritanceRepositoryFile = new File(postInheritanceRepositoryDir,
POST_INHERITANCE_REPOSITORY_FILE_NAME + ".json");
Map<StringFormat, String> strs = new HashMap<StringFormat, String>();
serializeRepositoryIntoFormats(repository, strs);
writeStringToFile(xmlPostInheritanceRepositoryFile, strs.get(StringFormat.XML));
writeStringToFile(jsonPostInheritanceRepositoryFile, strs.get(StringFormat.JSON));
}
}
static void serializeRepositoryIntoFormats(MetaMetadataRepository repository,
Map<StringFormat, String> strs)
{
SimplTypesScope.graphSwitch = GRAPH_SWITCH.ON;
repository.traverseAndInheritMetaMetadata();
strs.put(StringFormat.XML, trySerializeRepository(repository, StringFormat.XML));
strs.put(StringFormat.JSON, trySerializeRepository(repository, StringFormat.JSON));
}
private static String trySerializeRepository(MetaMetadataRepository repository, StringFormat format)
{
try
{
return SimplTypesScope.serialize(repository, format).toString();
}
catch (SIMPLTranslationException e)
{
Debug.error(MetaMetadataCompiler.class,
"Cannot serialize post-inheritance repository in format " + format);
e.printStackTrace();
}
return null;
}
private static void writeStringToFile(File file, String str)
{
BufferedWriter bw;
try
{
bw = new BufferedWriter(new FileWriter(file));
bw.write(str);
bw.close();
}
catch (IOException e)
{
Debug.error(MetaMetadataCompiler.class, "Cannot write to " + file);
e.printStackTrace();
}
}
private static void error(String msg)
{
Debug.error(MetaMetadataCompiler.class, msg);
}
/**
* @param args
*
* @throws IOException
* @throws SIMPLTranslationException
* @throws CodeTranslationException
*/
public static void main(String[] args) throws IOException, SIMPLTranslationException,
CodeTranslationException
{
if (args.length < 2 || args.length > 3)
{
error("args: <target-language> <generated-semantics-location> [<generated-builtin-declarations-location>]");
error(" - <target-language>: e.g. java or csharp (cs, c#).");
error(" - <generated-semantics-location>: the path to the location for generated semantics.");
error(" - <generated-builtin-declarations-location>: the path to the location for generated builtin declarations.");
System.exit(-1);
}
String lang = args[0].toLowerCase();
String semanticsLoc = args[1];
String builtinDeclarationsLoc = args.length == 3 ? args[2] : null;
File generatedSemanticsLocation = new File(semanticsLoc);
File generatedBuiltinSemanticsLocation = builtinDeclarationsLoc == null ? null : new File(builtinDeclarationsLoc);
CompilerConfig config = new CompilerConfig(lang, generatedSemanticsLocation, generatedBuiltinSemanticsLocation);
MetaMetadataCompiler compiler = new MetaMetadataCompiler();
compiler.compile(config);
}
}