/**
* 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.
*
* See the NOTICE file distributed with this work for additional
* information regarding copyright ownership.
*/
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.thingml.compilers.commandline;
import com.beust.jcommander.JCommander;
import com.beust.jcommander.Parameter;
import org.sintef.thingml.Configuration;
import org.sintef.thingml.ThingMLModel;
import org.sintef.thingml.constraints.ThingMLHelpers;
import org.thingml.compilers.ThingMLCompiler;
import org.thingml.compilers.registry.ThingMLCompilerRegistry;
import org.thingml.compilers.registry.ThingMLToolRegistry;
import org.thingml.thingmltools.ThingMLTool;
import java.io.File;
/**
* Created by ffl on 15.06.15.
*/
public class Main {
@Parameter(names = {"--source", "-s"}, description = "A thingml file to compile (should include at least one configuration)")
String source;
@Parameter(names = {"--output", "-o"}, description = "Optional output directory - by default current directory is used")
String output;
@Parameter(names = {"--compiler", "-c"}, description = "Compiler ID (Mandatory unless --tool (-t) is used)")
String compiler;
@Parameter(names = {"--tool", "-t"}, description = "Tool ID (Mandatory unless --compiler (-c) is used)")
String tool;
@Parameter(names = {"--options"}, description = "additional options for ThingML tools.")
String tooloptions;
boolean toolUsed, compilerUsed;
@Parameter(names = {"--help", "-h"}, help = true, description = "Display this message.")
private boolean help;
@Parameter(names = {"--create-dir", "-d"}, description = "Create a new directory named after the configuration for the output")
private boolean createDir;
@Parameter(names = {"--list-plugins"}, description = "Display the list of available plugins")
private boolean listPlugins;
public static void printUsage(JCommander jcom, ThingMLCompilerRegistry registry, ThingMLToolRegistry toolregistry) {
System.out.println(" --- ThingML help ---");
System.out.println("Typical usages: ");
System.out.println(" java -jar your-jar.jar -c <compiler> -s <source> [-o <output-dir>][-d]");
System.out.println(" java -jar your-jar.jar -t <tool> -s <source> [-o <output-dir>] [--options <option>]");
jcom.usage();
System.out.println("Compiler Id must belong to the following list:");
for (ThingMLCompiler c : registry.getCompilerPrototypes()) {
System.out.println(" └╼ " + c.getID() + "\t- " + c.getDescription());
}
System.out.println();
System.out.println("Tool Id must belong to the following list:");
for (ThingMLTool t : toolregistry.getToolPrototypes()) {
System.out.println(" └╼ " + t.getID() + "\t- " + t.getDescription());
}
}
public static void printPluginList(JCommander jcom, ThingMLCompilerRegistry registry, ThingMLToolRegistry toolregistry) {
registry.printNetworkPluginList();
System.out.println();
registry.printSerializationPluginList();
System.out.println();
registry.printExternalThingPluginList();
}
public static void main(String[] args) {
Main main = new Main();
ThingMLCompilerRegistry registry = ThingMLCompilerRegistry.getInstance();
ThingMLToolRegistry toolregistry = ThingMLToolRegistry.getInstance();
JCommander jcom = new JCommander(main, args);
// HELP Handling
if (main.help || ((main.compiler == null) && (main.tool == null) && (!main.listPlugins))) {
printUsage(jcom, registry, toolregistry);
if (main.listPlugins) {
System.out.println();
printPluginList(jcom, registry, toolregistry);
}
return;
}
if (main.listPlugins) {
printPluginList(jcom, registry, toolregistry);
return;
}
// COMPILER/TOOL Handling
main.toolUsed = main.tool != null;
main.compilerUsed = main.compiler != null;
if (!((main.compiler != null) ^ (main.tool != null))) {
System.out.println("One (and only one) of the option --compiler or --tool must be used (or their short version -c and -t).");
return;
}
//SOURCE Handling
File input = null;
if (main.source != null) {
input = new File(main.source);
} else {
System.out.println("--source (or -s) is a mandatory parameter.");
return;
}
if (!input.exists() || !input.isFile() || !input.canRead()) {
System.out.println("ERROR: Cannot find or read input file " + input.getAbsolutePath() + ".");
return;
}
//OUTPUT Handling
File outdir = null;
if (main.output != null) {
File o = new File(main.output);
if (!o.exists()) {
new File(main.output).mkdirs();
}
if (!o.exists() || !o.isDirectory() || !o.canWrite()) {
System.out.println("ERROR: Cannot find or write in output dir " + o.getAbsolutePath() + ".");
return;
}
outdir = o;
} else {
outdir = new File(System.getProperty("user.dir"));
}
//INPUT Handling
File indir = input.getAbsoluteFile().getParentFile();
if (indir == null || !indir.exists() || !indir.isDirectory() || !indir.canRead()) {
System.out.println("ERROR: Cannot find or read in input dir " + ((indir != null) ? indir.getAbsolutePath() : "") + ".");
return;
}
//RECAP
System.out.print("Running ThingML");
if (main.compiler != null)
System.out.print(" -c " + main.compiler);
if (main.tool != null)
System.out.print(" -t " + main.tool);
System.out.print(" -s " + main.source);
if (main.output != null)
System.out.print(" -o " + main.output);
System.out.println();
//EXECUTION
try {
ThingMLModel input_model = ThingMLCompiler.loadModel(input);
if (input_model == null) {
System.out.println("ERROR: The input model contains errors.");
return;
}
if (main.toolUsed) {
ThingMLTool thingmlTool = toolregistry.createToolInstanceByName(main.tool.trim());
if (thingmlTool == null) {
System.out.println("ERROR: Cannot find tool " + main.tool.trim() + ". Use --help (or -h) to check the list of registered compilers.");
return;
}
thingmlTool.setOutputDirectory(outdir);
//thingmlTool.setInputDirectory(indir); // TODO: Jakob
thingmlTool.options = main.tooloptions;
System.out.println("Generating code for input model. ");
thingmlTool.setSourceFile(input);
thingmlTool.generateThingMLFrom(input_model);
}
if (main.compilerUsed) {
if (ThingMLHelpers.allConfigurations(input_model).isEmpty()) {
System.out.println("ERROR: The input model does not contain any configuration to be compiled.");
return;
}
for (Configuration cfg : ThingMLHelpers.allConfigurations(input_model)) {
ThingMLCompiler thingmlCompiler = registry.createCompilerInstanceByName(main.compiler.trim());
if (thingmlCompiler == null) {
System.out.println("ERROR: Cannot find compiler " + main.compiler.trim() + ". Use --help (or -h) to check the list of registered compilers.");
return;
}
if (main.createDir)
outdir = new File(outdir, cfg.getName());
thingmlCompiler.setOutputDirectory(outdir);
thingmlCompiler.setInputDirectory(indir);
System.out.println("Generating code for configuration: " + cfg.getName());
thingmlCompiler.compile(cfg);
}
}
System.out.println("SUCCESS.");
} catch (Throwable ex) {
System.out.println("FATAL ERROR: " + ex.getMessage());
System.out.println("Please contact the ThingML development team (though GitHub's issue tracker) with 1) your input model, and 2) the following stack trace:");
ex.printStackTrace();
return;
}
return;
}
}