/*
* #%~
* Code Generator Plugin
* %%
* Copyright (C) 2008 - 2014 Overture
* %%
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this program. If not, see
* <http://www.gnu.org/licenses/gpl-3.0.html>.
* #~%
*/
package org.overture.ide.plugins.javagen.util;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IWorkspace;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.preferences.InstanceScope;
import org.eclipse.debug.core.DebugPlugin;
import org.eclipse.debug.core.ILaunchConfiguration;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.dialogs.ElementListSelectionDialog;
import org.eclipse.ui.handlers.HandlerUtil;
import org.osgi.service.prefs.Preferences;
import org.overture.ast.definitions.SClassDefinition;
import org.overture.ast.intf.lex.ILexLocation;
import org.overture.ast.lex.Dialect;
import org.overture.ast.modules.AModuleModules;
import org.overture.ast.node.INode;
import org.overture.codegen.analysis.violations.Violation;
import org.overture.codegen.assistant.LocationAssistantIR;
import org.overture.codegen.ir.VdmNodeInfo;
import org.overture.codegen.utils.GeneralCodeGenUtils;
import org.overture.codegen.vdm2java.JavaSettings;
import org.overture.ide.core.resources.IVdmProject;
import org.overture.ide.core.resources.IVdmSourceUnit;
import org.overture.ide.core.utility.FileUtility;
import org.overture.ide.debug.core.IDebugConstants;
import org.overture.ide.plugins.javagen.CodeGenConsole;
import org.overture.ide.plugins.javagen.ICodeGenConstants;
import org.overture.ide.plugins.javagen.commands.Vdm2JavaCommand;
public class PluginVdm2JavaUtil
{
public static final String CODEGEN_RUNTIME_LIB_FOLDER = "lib";
public static final String CODEGEN_RUNTIME_BIN_FILE = "codegen-runtime.jar";
public static final String CODEGEN_RUNTIME_SOURCES_FILE = "codegen-runtime-sources.jar";
public static final String VDM2JML_RUNTIME_BIN_FILE = "vdm2jml-runtime.jar";
public static final String VDM2JML_RUNTIME_SOURCES_FILE = "vdm2jml-runtime-sources.jar";
public static final String ECLIPSE_CLASSPATH_TEMPLATE_FILE = "cg.classpath";
public static final String ECLIPSE_PROJECT_TEMPLATE_FILE = "cg.project";
public static final String ECLIPSE_PROJECT_ROOT_FOLDER = "java";
public static final String ECLIPSE_CLASSPATH_FILE = ".classpath";
public static final String ECLIPSE_PROJECT_FILE = ".project";
public static final String ECLIPSE_RES_FILES_FOLDER = "eclipsefiles";
public static final String ECLIPSE_PROJECT_SRC_FOLDER = "src";
public static final String RUNTIME_CLASSPATH_ENTRY = "<classpathentry kind=\"lib\" path=\"lib/codegen-runtime.jar\"/>\n";
public static final String VDM2JML_CLASSPATH_ENTRY = "<classpathentry kind=\"lib\" path=\"lib/vdm2jml-runtime.jar\"/>\n";
public static final String WARNING = "[WARNING]";
private PluginVdm2JavaUtil()
{
}
public static IFile convert(File file)
{
IWorkspace workspace = ResourcesPlugin.getWorkspace();
IPath location = Path.fromOSString(file.getAbsolutePath());
IFile iFile = workspace.getRoot().getFileForLocation(location);
return iFile;
}
public static IVdmProject getVdmProject(ExecutionEvent event)
{
ISelection selection = HandlerUtil.getCurrentSelection(event);
if (!(selection instanceof IStructuredSelection))
{
return null;
}
IStructuredSelection structuredSelection = (IStructuredSelection) selection;
Object firstElement = structuredSelection.getFirstElement();
if (!(firstElement instanceof IProject))
{
return null;
}
IProject project = (IProject) firstElement;
IVdmProject vdmProject = (IVdmProject) project.getAdapter(IVdmProject.class);
return vdmProject;
}
public static List<INode> getNodes(List<IVdmSourceUnit> sources)
{
List<INode> nodes = new ArrayList<INode>();
for (IVdmSourceUnit source : sources)
{
nodes.addAll(source.getParseList());
}
return nodes;
}
public static List<SClassDefinition> getClasses(
List<IVdmSourceUnit> sources)
{
List<SClassDefinition> classes = new LinkedList<SClassDefinition>();
for(INode n : getNodes(sources))
{
if(n instanceof SClassDefinition)
{
classes.add((SClassDefinition) n);
}
}
return classes;
}
public static List<AModuleModules> getModules(List<IVdmSourceUnit> sources)
{
List<AModuleModules> modules = new LinkedList<AModuleModules>();
for(INode n : getNodes(sources))
{
if(n instanceof AModuleModules)
{
modules.add((AModuleModules) n);
}
}
return modules;
}
public static File getEclipseProjectFolder(IVdmProject project)
{
return new File(getProjectDir(project), ECLIPSE_PROJECT_ROOT_FOLDER);
}
public static File getCodeGenRuntimeLibFolder(IVdmProject project)
{
return getFolder(getEclipseProjectFolder(project), CODEGEN_RUNTIME_LIB_FOLDER);
}
public static File getJavaCodeOutputFolder(IVdmProject project, JavaSettings settings)
throws CoreException
{
File outputDir = getEclipseProjectFolder(project);
outputDir = getFolder(outputDir, ECLIPSE_PROJECT_SRC_FOLDER);
return outputDir;
}
public static void addMarkers(String generalMessage,
Set<Violation> violations)
{
List<Violation> list = GeneralCodeGenUtils.asSortedList(violations);
for (Violation violation : list)
{
IFile ifile = convert(violation.getLocation().getFile());
FileUtility.addMarker(ifile, generalMessage + ": "
+ violation.getDescripton(), violation.getLocation(), IMarker.PRIORITY_NORMAL, ICodeGenConstants.PLUGIN_ID, -1);
}
}
public static String limitStr(String str)
{
if (str == null)
{
return "";
}
int length = str.length();
final int limit = 100;
String subString = null;
if (length <= limit)
{
subString = str.substring(0, length);
} else
{
subString = str.substring(0, limit) + "...";
}
return subString.replaceAll("\\s+", " ");
}
public static String formatNodeString(VdmNodeInfo nodeInfo,
LocationAssistantIR locationAssistant)
{
INode node = nodeInfo.getNode();
StringBuilder messageSb = new StringBuilder();
messageSb.append(limitStr(node.toString()));
messageSb.append(" (" + node.getClass().getSimpleName() + ")");
ILexLocation location = locationAssistant.findLocation(node);
if (location != null)
{
messageSb.append(" " + location.toShortString() + " in " + location.getFile().getAbsolutePath());
}
String reason = nodeInfo.getReason();
if (reason != null)
{
messageSb.append(". Reason: " + reason);
}
return messageSb.toString();
}
public static void addMarkers(VdmNodeInfo nodeInfo,
LocationAssistantIR locationAssistant)
{
if (nodeInfo == null)
{
return;
}
INode node = nodeInfo.getNode();
ILexLocation location = locationAssistant.findLocation(node);
if (location == null)
{
return;
}
IFile ifile = convert(location.getFile());
String reason = nodeInfo.getReason();
String message = "Code generation support not implemented: "
+ node.toString();
message += reason != null ? ". Reason: " + reason : "";
FileUtility.addMarker(ifile, message, location, IMarker.PRIORITY_NORMAL, ICodeGenConstants.PLUGIN_ID, -1);
}
private static File getProjectDir(IVdmProject project)
{
return project.getModelBuildPath().getOutput().getLocation().toFile();
}
private static File getFolder(File parent, String folder)
{
File resultingFolder = new File(parent, folder);
resultingFolder.mkdirs();
return resultingFolder;
}
public static void copyCodeGenFile(String inOutFileName, File outputFolder)
throws IOException
{
copyCodeGenFile(inOutFileName, inOutFileName, outputFolder);
}
public static void copyCodeGenFile(String inputFileName,
String outputFileName, File outputFolder) throws IOException
{
InputStream input = Vdm2JavaCommand.class.getResourceAsStream('/' + inputFileName);
if (input == null)
{
throw new IOException("Could not find resource: " + inputFileName);
}
byte[] buffer = new byte[8 * 1024];
try
{
File outputFile = new File(outputFolder, outputFileName);
outputFile.getParentFile().mkdirs();
if (!outputFile.exists())
{
outputFile.createNewFile();
}
OutputStream output = new FileOutputStream(outputFile);
try
{
int bytesRead;
while ((bytesRead = input.read(buffer)) != -1)
{
output.write(buffer, 0, bytesRead);
}
} finally
{
output.close();
}
} finally
{
input.close();
}
}
public static List<String> getClassesToSkip()
{
Preferences preferences = InstanceScope.INSTANCE.getNode(ICodeGenConstants.PLUGIN_ID);
String userInput = preferences.get(ICodeGenConstants.CLASSES_TO_SKIP, ICodeGenConstants.CLASSES_TO_SKIP_DEFAULT);
return GeneralCodeGenUtils.getClassesToSkip(userInput);
}
public static String dialog(List<LaunchConfigData> launchConfigs)
{
Shell shell = PlatformUI.getWorkbench().getDisplay().getActiveShell();
ElementListSelectionDialog dialog = new ElementListSelectionDialog(shell, new LabelProvider());
dialog.setTitle("Launch Configuration Selection");
dialog.setMessage("Select a Launch configuration (* = any string, ? = any char):");
dialog.setMultipleSelection(false);
dialog.setElements(launchConfigs.toArray());
int resCode = dialog.open();
if (resCode == ElementListSelectionDialog.OK)
{
Object[] dialogResult = dialog.getResult();
if (dialogResult.length == 1
&& dialogResult[0] instanceof LaunchConfigData)
{
LaunchConfigData chosenConfig = (LaunchConfigData) dialogResult[0];
return chosenConfig.getExp();
}
}
return null;
}
public static List<LaunchConfigData> getProjectLaunchConfigs(final IProject project)
{
List<LaunchConfigData> matches = new LinkedList<>();
try
{
ILaunchConfiguration[] configs = DebugPlugin.getDefault().getLaunchManager().getLaunchConfigurations();
for (ILaunchConfiguration launchConfig : configs)
{
String launchConfigProjectName = launchConfig.getAttribute(IDebugConstants.VDM_LAUNCH_CONFIG_PROJECT, "");
if (launchConfigProjectName != null && !launchConfigProjectName.equals("")
&& launchConfigProjectName.equals(project.getName()))
{
String exp = launchConfig.getAttribute(IDebugConstants.VDM_LAUNCH_CONFIG_EXPRESSION, "");
matches.add(new LaunchConfigData(launchConfig.getName(), exp));
}
}
} catch (CoreException e)
{
CodeGenConsole.GetInstance().errorln("Problem looking up launch configurations for project "
+ project.getName() + ": " + e.getMessage());
e.printStackTrace();
}
return matches;
}
public static String dialect2Str(Dialect dialect)
{
if(dialect == Dialect.VDM_SL)
{
return "VDM-SL";
}
else if(dialect == Dialect.VDM_PP)
{
return "VDM++";
}
else if(dialect == Dialect.VDM_RT)
{
return "VDM-RT";
}
else
{
return null;
}
}
}