/* * Copyright 2012 PRODYNA AG * * Licensed under the Eclipse Public License (EPL), Version 1.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.opensource.org/licenses/eclipse-1.0.php or * http://www.nabucco.org/License.html * * 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 org.nabucco.framework.generator; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.List; import org.nabucco.framework.generator.compiler.NabuccoCompilationTarget; import org.nabucco.framework.generator.compiler.NabuccoCompiler; import org.nabucco.framework.generator.compiler.NabuccoCompilerException; import org.nabucco.framework.generator.compiler.NabuccoCompilerOptions; import org.nabucco.framework.generator.compiler.NabuccoCompilerOptionType; import org.nabucco.framework.generator.parser.file.NabuccoFile; import org.nabucco.framework.generator.parser.model.NabuccoModel; import org.nabucco.framework.generator.parser.model.NabuccoModelLoader; import org.nabucco.framework.mda.logger.MdaLogger; import org.nabucco.framework.mda.logger.MdaLoggingFactory; import org.nabucco.framework.mda.model.MdaModel; import org.nabucco.framework.mda.model.ModelException; /** * The NabuccoGenerator parses an appropriate NABUCCO nabuccoFileList nabuccoFileList, compiles and * validates the parsed model and generates target models out of it. * * @author Nicolas Moser, PRODYNA AG */ public final class NabuccoGenerator { private boolean isRun = false; private NabuccoCompilerOptions options; private String projectName; private String projectPath; private List<NabuccoFile> nabuccoFileList = new ArrayList<NabuccoFile>(); private static MdaLogger logger = MdaLoggingFactory.getInstance().getLogger(NabuccoGenerator.class); /** * Creates a new {@link NabuccoGenerator} instance for an appropriate .nbc file. * * @param nabuccoFile * the .nbc file */ public NabuccoGenerator(NabuccoFile nabuccoFile) { if (nabuccoFile == null) { throw new IllegalArgumentException("NABUCCO file is not valid."); } this.nabuccoFileList.add(nabuccoFile); this.initCompilerOptions(null); } /** * Creates a new {@link NabuccoGenerator} instance for an appropriate {@link NabuccoFile} with * generator options. * * @param nabuccoFile * the NABUCCO file * @param properties * .properties nabuccoFileList containing NABUCCO compiler options */ public NabuccoGenerator(NabuccoFile nabuccoFile, File properties) { if (nabuccoFile == null) { throw new IllegalArgumentException("NABUCCO file is not valid."); } this.nabuccoFileList.add(nabuccoFile); this.initCompilerOptions(properties); } /** * Creates a new {@link NabuccoGenerator} instance for an appropriate {@link NabuccoFile} with * generator options. * * @param nabuccoFile * the NABUCCO file * @param options * the NABUCCO compiler options */ public NabuccoGenerator(NabuccoFile nabuccoFile, NabuccoCompilerOptions options) { if (nabuccoFile == null) { throw new IllegalArgumentException("NABUCCO file is not valid."); } if (options == null) { initCompilerOptions(null); } this.nabuccoFileList.add(nabuccoFile); this.options = options; } /** * Creates a new {@link NabuccoGenerator} instance for an appropriate {@link NabuccoFile} with * generator options. * * @param nabuccoFileList * the NABUCCO nabuccoFileList */ public NabuccoGenerator(List<NabuccoFile> nabuccoFileList) { if (nabuccoFileList == null) { throw new IllegalArgumentException("NABUCCO file list is not valid."); } if (options == null) { initCompilerOptions(null); } this.nabuccoFileList.addAll(nabuccoFileList); this.initCompilerOptions(null); } /** * Creates a new {@link NabuccoGenerator} instance for an appropriate {@link NabuccoFile} with * generator options. * * @param nabuccoFileList * the NABUCCO nabuccoFileList * @param options * the NABUCCO compiler options */ public NabuccoGenerator(List<NabuccoFile> nabuccoFileList, NabuccoCompilerOptions options) { if (nabuccoFileList == null) { throw new IllegalArgumentException("NABUCCO file list is not valid."); } if (options == null) { initCompilerOptions(null); } else { this.options = new NabuccoCompilerOptions(options); } this.nabuccoFileList.addAll(nabuccoFileList); } /** * Initializes the compiler options for the given .properties file. * * @param propertiesFile * the properties file */ private void initCompilerOptions(File propertiesFile) { if (propertiesFile == null) { logger.debug("No compiler properties defined. Using default NABUCCO properties."); this.options = NabuccoCompilerOptions.getDefaultOptions(); } else { try { this.options = new NabuccoCompilerOptions(propertiesFile); } catch (IOException e) { logger.warning("Compiler properties [", propertiesFile.getName() + "] not valid. ", e.getMessage(), " Using default NABUCCO properties."); this.options = NabuccoCompilerOptions.getDefaultOptions(); } } } /** * Executes the compilation process and generates target models out of it. * * @throws NabuccoGeneratorException */ public void generate() throws NabuccoGeneratorException { this.printHeading(); this.validateFileList(); logger.info("Start generating NABUCCO:"); logger.info("Compiling in project '", this.projectName, "'."); if (this.nabuccoFileList.isEmpty()) { logger.warning("No NABUCCO files selected for generation."); return; } try { this.generateFileList(); this.isRun = true; } catch (ModelException me) { logger.error(me, "Error loading NABUCCO model."); throw new NabuccoGeneratorException("Error loading NABUCCO model: " + nabuccoFileList, me); } catch (NabuccoCompilerException ce) { logger.error(ce, "Error compiling NABUCCO model."); throw new NabuccoGeneratorException("Error compiling NABUCCO model: " + nabuccoFileList, ce); } catch (Exception e) { logger.error(e, "Error generating NABUCCO model."); throw new NabuccoGeneratorException("Error generating NABUCCO model: " + nabuccoFileList, e); } } /** * Print the NABUCCO Generator Heading. */ private void printHeading() { StringBuilder heading = new StringBuilder(); heading.append("\n\n"); heading.append(" ###############################################################################\n"); heading.append(" # #\n"); heading.append(" # NABUCCO Framework Generator - (2009-2012) PRODYNA AG, Germany. #\n"); heading.append(" # #\n"); heading.append(" # http://nabucco.org/ https://github.com/nabucco/ #\n"); heading.append(" # #\n"); heading.append(" ###############################################################################\n"); logger.info(heading.toString()); } /** * Validates the NABUCCO file list and extract project information. * * @throws NabuccoGeneratorException */ private void validateFileList() throws NabuccoGeneratorException { if (this.isRun) { throw new NabuccoGeneratorException("Generator must not be invoked multiple times."); } if (this.nabuccoFileList.size() < 1) { logger.warning("No NABUCCO files selected."); return; } NabuccoFile nabuccoFile = this.nabuccoFileList.get(0); this.projectName = nabuccoFile.getProjectName(); this.projectPath = nabuccoFile.getProjectPath(); } /** * Generates a NABUCCO directory. * * @throws Exception */ private void generateFileList() throws Exception { List<NabuccoFile> fileList = new ArrayList<NabuccoFile>(); for (NabuccoFile nabuccoFile : this.nabuccoFileList) { if (nabuccoFile.isDirectory()) { fileList.addAll(nabuccoFile.listNabuccoFiles()); } else { fileList.add(nabuccoFile); } } if (fileList.isEmpty()) { logger.warning("No NABUCCO files selected for generation."); return; } int size = fileList.size(); String target = this.options.getOption(NabuccoCompilerOptionType.OUT_DIR); if (size > 1) { logger.info("Compiling ", String.valueOf(size), " NABUCCO files to '", target, "'."); } else { logger.info("Compiling ", String.valueOf(size), " NABUCCO file to '", target, "'."); } List<MdaModel<NabuccoModel>> modelList = new ArrayList<MdaModel<NabuccoModel>>(); for (NabuccoFile nabuccoFile : fileList) { modelList.add(this.loadModel(nabuccoFile)); } long before = System.currentTimeMillis(); this.compileModel(modelList); long after = System.currentTimeMillis(); logger.info("Generation finished successfully after " + ((after - before) / 1000.0) + "s."); } /** * Loads the NABUCCO model from a NABUCCO nabuccoFileList. * * @param file * the nabucco file to load * * @return the loaded model * * @throws ModelException */ private MdaModel<NabuccoModel> loadModel(NabuccoFile file) throws ModelException { String targetDirectory = this.options.getOption(NabuccoCompilerOptionType.OUT_DIR); NabuccoModelLoader modelLoader = new NabuccoModelLoader(targetDirectory); NabuccoModel nabuccoModel = modelLoader.loadModel(file); return new MdaModel<NabuccoModel>(nabuccoModel); } /** * Compiles a NABUCCO model and generates code. * * @param modelList * the list of NABUCCO models * * @throws NabuccoCompilerException */ private void compileModel(List<MdaModel<NabuccoModel>> modelList) throws NabuccoCompilerException, NabuccoGeneratorException { String component = this.projectName; for (NabuccoFile nabuccoFile : nabuccoFileList) { if (component != null && !component.equals(nabuccoFile.getProjectName())) { throw new NabuccoGeneratorException("Cannot generate over multiple components."); } } StringBuilder rootDir = new StringBuilder(); rootDir.append(this.projectPath); rootDir.append(File.separatorChar); rootDir.append(".."); NabuccoCompilationTarget target = new NabuccoCompilationTarget(modelList, rootDir.toString(), component); NabuccoCompiler compiler = new NabuccoCompiler(this.options); compiler.compile(target); } }