/** * 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. */ package org.thingml.eclipse.ui.commands; import java.io.PrintStream; import java.util.ArrayList; import java.util.HashSet; import java.util.Iterator; import java.util.ServiceLoader; import java.util.Set; import org.eclipse.core.commands.ExecutionEvent; import org.eclipse.core.commands.ExecutionException; import org.eclipse.core.commands.IHandler; import org.eclipse.core.commands.IHandlerListener; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.jface.preference.IPreferenceStore; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.ui.handlers.HandlerUtil; 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.checker.Checker.CheckerInfo; import org.thingml.compilers.registry.ThingMLCompilerRegistry; import org.thingml.compilers.spi.NetworkPlugin; import org.thingml.compilers.spi.SerializationPlugin; import org.thingml.compilers.uml.PlantUMLCompiler; import org.thingml.compilers.uml.PlantUMLThingImplCompiler; import org.thingml.compilers.utils.ThingMLPrettyPrinter; import org.thingml.eclipse.preferences.PreferenceConstants; import org.thingml.eclipse.ui.Activator; import org.thingml.eclipse.ui.ThingMLConsole; public class CompileThingFile implements IHandler { private static ServiceLoader<NetworkPlugin> plugins = ServiceLoader.load(NetworkPlugin.class); private static Set<NetworkPlugin> loadedPlugins; private static ServiceLoader<SerializationPlugin> serPlugins = ServiceLoader.load(SerializationPlugin.class); private static Set<SerializationPlugin> loadedSerPlugins; IPreferenceStore store = Activator.getDefault().getPreferenceStore(); static { loadedPlugins = new HashSet<>(); plugins.reload(); Iterator<NetworkPlugin> it = plugins.iterator(); ThingMLConsole.getInstance().printMessage("Loading network plugins:\n"); while(it.hasNext()) { NetworkPlugin p = it.next(); loadedPlugins.add(p); ThingMLConsole.getInstance().printMessage("\t-" + p.getName() + "\n"); } loadedSerPlugins = new HashSet<>(); serPlugins.reload(); Iterator<SerializationPlugin> sit = serPlugins.iterator(); ThingMLConsole.getInstance().printMessage("Loading serialization plugins:\n"); while(sit.hasNext()) { SerializationPlugin sp = sit.next(); loadedSerPlugins.add(sp); ThingMLConsole.getInstance().printMessage("\t-" + sp.getName() + "\n"); } } @Override public void addHandlerListener(IHandlerListener handlerListener) { // TODO Auto-generated method stub } @Override public void dispose() { // TODO Auto-generated method stub } @Override public Object execute(ExecutionEvent event) throws ExecutionException { ThingMLConsole.getInstance().printDebug("\n\n********************************************************************************\n"); try { // Fetch the compiler to be used String compilerName = event.getParameter("org.thingml.eclipse.ui.commandParameterCompilerName").toString(); String subCompiler = null; if (compilerName.contains("/")) { subCompiler = compilerName.split("/")[1]; compilerName = compilerName.split("/")[0]; } ThingMLCompiler compiler = ThingMLCompilerRegistry.getInstance().createCompilerInstanceByName(compilerName); for(NetworkPlugin np : loadedPlugins) { for(String lang : np.getTargetedLanguages()) if(lang.compareTo(compiler.getID()) == 0) { compiler.addNetworkPlugin(np); } } for(SerializationPlugin sp : loadedSerPlugins) { if(sp.getTargetedLanguages().contains(compiler.getID())) { compiler.addSerializationPlugin(sp); } } if (compiler instanceof PlantUMLCompiler) { PlantUMLThingImplCompiler.FACTORIZE_TRANSITIONS = store.getBoolean(PreferenceConstants.UML_FACTORIZE); ThingMLPrettyPrinter.HIDE_BLOCKS = store.getBoolean(PreferenceConstants.UML_HIDE_BLOCK); ThingMLPrettyPrinter.MAX_BLOCK_SIZE = store.getInt(PreferenceConstants.UML_BLOCK_SIZE); ThingMLPrettyPrinter.USE_ELLIPSIS_FOR_PARAMS = store.getBoolean(PreferenceConstants.UML_ELLIPSIS); } ThingMLConsole.getInstance().printDebug("Compiling with \"" + compiler.getName() + "\" (Platform: " + compiler.getID() + ")\n"); // Fetch the input model to be used IFile target_file = null; ISelection selection = HandlerUtil.getActiveWorkbenchWindow(event).getActivePage().getSelection(); if (selection != null & selection instanceof IStructuredSelection) { IStructuredSelection strucSelection = (IStructuredSelection) selection; if (!strucSelection.isEmpty() && strucSelection.getFirstElement() instanceof IFile) { target_file = (IFile) strucSelection.getFirstElement(); } else { ThingMLConsole.getInstance().printError("ERROR: The selection is empty or does not contains a ThingML file. Compilation stopped.\n"); return null; } if (strucSelection.size() > 1) { ThingMLConsole.getInstance().printDebug("WARNING: Selection contains more than one model. Using the first and ingnoring others.\n"); } } java.io.File f = target_file.getLocation().toFile(); ThingMLConsole.getInstance().printDebug("Selected input file: " + target_file.toString() + " (" + f.getAbsolutePath() + ")\n"); ThingMLModel model = ThingMLCompiler.loadModel(f); if (model == null) { ThingMLConsole.getInstance().printError("ERROR: The selected model contains errors and will not be compiled. Please fix errors below\n"); for(String error : ThingMLCompiler.errors) { ThingMLConsole.getInstance().printError(error + "\n"); } ThingMLConsole.getInstance().printError("Compilation stopped.\n"); return null; } for(String warning : ThingMLCompiler.warnings) { ThingMLConsole.getInstance().printMessage(warning + "\n"); } /*System.out.println("checking......."); CheckThingMLFile.running = true; ILiveValidator validator = (ILiveValidator)ModelValidationService.getInstance().newValidator(EvaluationMode.LIVE); //validator.setIncludeLiveConstraints(true); //IStatus status = validator.validate(model); Resource r = ThingMLCompiler.resource; if (!r.eAdapters().contains(liveValidationContentAdapter)) { r.eAdapters().add(liveValidationContentAdapter); } CheckThingMLFile.running = false; System.out.println("done!");*/ // Look for a Configurations to compile ArrayList<Configuration> toCompile = new ArrayList<Configuration>(); for ( Configuration cfg : ThingMLHelpers.allConfigurations(model)) { toCompile.add(cfg); } if (toCompile.isEmpty()) { ThingMLConsole.getInstance().printError("ERROR: The selected model does not contain any concrete Configuration to compile. \n"); ThingMLConsole.getInstance().printError("Compilation stopped.\n"); return null; } /*for(Configuration cfg : toCompile) { ThingMLCompiler.checker.Errors.clear(); ThingMLCompiler.checker.Warnings.clear(); ThingMLCompiler.checker.Notices.clear(); ThingMLCompiler.checker.do_generic_check(cfg); if (ThingMLCompiler.checker.containsErrors()) { ThingMLConsole.getInstance().printError("ERROR: Configuration " + cfg.getName() + " contains errors and will not be compiled. Please fix errors below\n"); for(CheckerInfo err : ThingMLCompiler.checker.Errors) { System.out.println("debug: error: " + err.message); ThingMLConsole.getInstance().printError(err.message + "(" + err.source + ")"); } return null; } for(CheckerInfo err : ThingMLCompiler.checker.Warnings) { ThingMLConsole.getInstance().printError(err.message + "(" + err.source + ")"); } }*/ // Create the output directory in the current project in a folder "/thingml-gen/<platform>/" IProject project = target_file.getProject(); java.io.File project_folder = project.getLocation().toFile(); java.io.File thingmlgen_folder = new java.io.File(project_folder, "thingml-gen"); if (!thingmlgen_folder.exists()) { ThingMLConsole.getInstance().printDebug("Creating thingml-gen folder in " + project_folder.getAbsolutePath() + "\n"); thingmlgen_folder.mkdir(); } java.io.File platform_folder = new java.io.File(thingmlgen_folder, compiler.getID()); /*if (platform_folder.exists()) { ThingMLConsole.getInstance().printDebug("Cleaning folder " + compiler.getID() + " in "+ thingmlgen_folder.getAbsolutePath() + "\n"); ThingMLConsole.getInstance().emptyFolder(platform_folder); } else { ThingMLConsole.getInstance().printDebug("Creating folder " + compiler.getID() + " in "+ thingmlgen_folder.getAbsolutePath() + "\n"); platform_folder.mkdir(); } project.refreshLocal(IResource.DEPTH_INFINITE, null);*/ String pack = store.getString(PreferenceConstants.PACK_STRING); String[] options = new String[1]; options[0] = pack; // Compile all the configuration for ( Configuration cfg : toCompile ) { java.io.File cfg_folder = new java.io.File(platform_folder, cfg.getName()); java.io.File in_folder = f.getAbsoluteFile().getParentFile(); if (cfg_folder.exists()) { ThingMLConsole.getInstance().printDebug("Cleaning folder " + cfg_folder.getAbsolutePath() + "\n"); ThingMLConsole.getInstance().emptyFolder(cfg_folder); } else { ThingMLConsole.getInstance().printDebug("Creating folder " + cfg_folder.getAbsolutePath() + "\n"); cfg_folder.mkdir(); } compiler = ThingMLCompilerRegistry.getInstance().createCompilerInstanceByName(compilerName); compiler.setOutputDirectory(cfg_folder); compiler.setInputDirectory(in_folder); compiler.setErrorStream(ThingMLConsole.getInstance().getErrorSteam()); compiler.setMessageStream(ThingMLConsole.getInstance().getMessageSteam()); compiler.checker.Errors.clear(); compiler.checker.Warnings.clear(); compiler.checker.Notices.clear(); compiler.checker.do_check(cfg); ThingMLConsole.getInstance().printMessage("Configuration " + cfg.getName() + " contains " + compiler.checker.Errors.size() + " error(s), " + compiler.checker.Warnings.size() + " warning(s), and " + compiler.checker.Notices.size() + " notices.\n"); if (compiler.checker.Errors.size() > 0) { ThingMLConsole.getInstance().printMessage("Please fix the errors below. In future versions, we will block the code generation if errors are identified!\n"); } for(CheckerInfo i : compiler.checker.Errors) { ThingMLConsole.getInstance().printError(i.toString()); } for(CheckerInfo i : compiler.checker.Warnings) { ThingMLConsole.getInstance().printMessage(i.toString()); } if (store.getBoolean(PreferenceConstants.PRINT_NOTICE_STRING)) { for(CheckerInfo i : compiler.checker.Notices) { ThingMLConsole.getInstance().printMessage(i.toString()); } } compiler.compile(cfg, options); if(subCompiler != null) { ThingMLConsole.getInstance().printDebug("Compiling with connector compiler \"" + subCompiler + "\" (Platform: " + compiler.getID() + ")\n"); compiler.compileConnector(subCompiler, cfg); } ThingMLConsole.getInstance().printDebug("Configuration " + cfg.getName() + " compiled successfully.\n"); } project.refreshLocal(IResource.DEPTH_INFINITE, null); } catch (Throwable e) { ThingMLConsole.getInstance().printError("FATAL ERROR: Exeption calling ThingML Compiler: " + e.getLocalizedMessage()); ThingMLConsole.getInstance().printError("Please contact the ThingML development team (though GitHub's issue tracker) with 1) your input model, and 2) the following stack trace:"); e.printStackTrace(new PrintStream(ThingMLConsole.getInstance().getErrorSteam())); e.printStackTrace(); } return null; } @Override public boolean isEnabled() { return true; } @Override public boolean isHandled() { return true; } @Override public void removeHandlerListener(IHandlerListener handlerListener) { // TODO Auto-generated method stub } }