Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 12 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ GoogleMockのコード出力機能も持ちます。

変換ルールなどについては、次のWEBサイトを参照ください。

- [組込みソフト開発 ノウハウ集](http://y-philly.bitbucket.org/embedded-know-how/index.html)
- [組込みソフトウェア開発 ノウハウ集](http://y-philly.bitbucket.org/embedded-know-how/index.html)


## 1. インストール方法
Expand Down Expand Up @@ -52,6 +52,17 @@ Abstractなクラスを、型による動的インターフェイスとしてコ
## 3. テンプレートファイルについて
- テンプレートファイルの文字コードは、UTF-8 としてください。

## 4. オプション

本プラグインは、 コードフォーマッタ [Uncrustify](http://uncrustify.sourceforge.net/http://uncrustify.sourceforge.net/)
と連携して、生成コードを任意(プロジェクトごとのコーディングルールなど)の書式に整形することができます。

一度以下の手順を行えば、その後は生成コードに対する整形が自動で行われます。

1. Uncrustify のコンフィグファイルを作成し、 `custom.cfg` という名前で保存します。
1. フォルダ `[ホームフォルダ]/.astah/[astahのエディション名]/plugins/uml2c/uncrustify` を作成します。
1. 上記フォルダに Uncrustify の実行ファイルと、`custom.cfg` を保存します。

## ライセンス
Copyright 2016 ChangeVision,Inc.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@

public class GenerateCSkeletonAction extends GenerateCodeAction {
@Override
protected void generateCode(AbstractCModule cModule, String outputDirPath) throws IOException {
protected void generateCode(AbstractCModule cModule, String outputDirPath)
throws IOException, InterruptedException {
CSkeletonGenerator cSkeletonGenerator = new CSkeletonGenerator(cModule);
cSkeletonGenerator.outputHeader(outputDirPath);
cSkeletonGenerator.outputSource(outputDirPath);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import com.change_vision.astah.extension.plugin.uml2c.cmodule.AbstractCModule;
import com.change_vision.astah.extension.plugin.uml2c.cmodule.CModuleFactory;
import com.change_vision.astah.extension.plugin.uml2c.codegenerator.CodeGenerator;
import com.change_vision.astah.extension.plugin.uml2c.astahutil.AstahUtil;
import com.change_vision.jude.api.inf.AstahAPI;
import com.change_vision.jude.api.inf.exception.InvalidUsingException;
import com.change_vision.jude.api.inf.exception.ProjectNotFoundException;
Expand All @@ -28,6 +29,7 @@
import com.change_vision.jude.api.inf.view.IDiagramViewManager;
import com.change_vision.jude.api.inf.view.IViewManager;


public abstract class GenerateCodeAction implements IPluginActionDelegate {
private static Logger logger = LoggerFactory.getLogger(CodeGenerator.class);

Expand All @@ -41,7 +43,7 @@ public Object run(IWindow window) throws UnExpectedException {
List<IClass> targetClasses = getTargetClasses(api);
if (targetClasses.isEmpty()) {
JOptionPane.showMessageDialog(window.getParent(),
Messages.getMessage("message.select_class"),
Messages.getMessage("message.select_class"),
Messages.getMessage("title.select_class"),
JOptionPane.WARNING_MESSAGE);
logger.warn("No target class was selected");
Expand All @@ -52,34 +54,34 @@ public Object run(IWindow window) throws UnExpectedException {
String outputDirPath = getOutputDirPath(window, projectAccessor);
logger.info("Output Path = {}", outputDirPath);
if (outputDirPath == null) return null; //canceled

if (!ensureWritableOutputFolder(outputDirPath, window)) {
return null;
}

for (IClass iClass: targetClasses) {
AbstractCModule cModule = CModuleFactory.getCModule(iClass);
logger.info("Module = {}", cModule.getClass().getSimpleName());
generateCode(cModule, outputDirPath);
}

JOptionPane.showMessageDialog(window.getParent(),
Messages.getMessage("message.finish_generating"),
JOptionPane.showMessageDialog(window.getParent(),
Messages.getMessage("message.finish_generating"),
Messages.getMessage("title.finish_generating"),
JOptionPane.INFORMATION_MESSAGE);
logger.info("Finished.");
} catch (ProjectNotFoundException e) {
logger.warn("Project Not Found.");
JOptionPane.showMessageDialog(window.getParent(),
Messages.getMessage("message.project_not_found"),
JOptionPane.showMessageDialog(window.getParent(),
Messages.getMessage("message.project_not_found"),
Messages.getMessage("title.project_not_found"),
JOptionPane.WARNING_MESSAGE);
} catch (ResourceNotFoundException e) {
logger.warn("Template Not Found.");
logger.warn(" - Template Search Path = {}", CodeGenerator.getAstahConfigPath());
logger.warn(" - Template Search Path = {}", AstahUtil.getFullPathOfConfigDir());
logger.warn(" - Exception = {}", e.getLocalizedMessage());
JOptionPane.showMessageDialog(window.getParent(),
Messages.getMessage("message.not_found_template", CodeGenerator.getAstahConfigPath(), e.getLocalizedMessage()),
JOptionPane.showMessageDialog(window.getParent(),
Messages.getMessage("message.not_found_template", AstahUtil.getFullPathOfConfigDir(), e.getLocalizedMessage()),
Messages.getMessage("title.not_found_template"),
JOptionPane.WARNING_MESSAGE);
} catch (Throwable e) {
Expand All @@ -92,8 +94,9 @@ public Object run(IWindow window) throws UnExpectedException {

return null;
}

protected abstract void generateCode(AbstractCModule cModule, String outputDirPath) throws IOException;

protected abstract void generateCode(AbstractCModule cModule, String outputDirPath)
throws IOException, InterruptedException;

private boolean ensureWritableOutputFolder(String outputDirPath, IWindow window) {
File outputDir = new File(outputDirPath);
Expand All @@ -102,7 +105,7 @@ private boolean ensureWritableOutputFolder(String outputDirPath, IWindow window)
if (!wasSucceeded) {
logger.warn("Failed to create a folder to output. path = {}", outputDir.getAbsolutePath());
JOptionPane.showMessageDialog(window.getParent(),
Messages.getMessage("message.failed_mkdirs", outputDir.getAbsolutePath()),
Messages.getMessage("message.failed_mkdirs", outputDir.getAbsolutePath()),
Messages.getMessage("title.failed_mkdirs"),
JOptionPane.WARNING_MESSAGE);
return false;
Expand All @@ -112,7 +115,7 @@ private boolean ensureWritableOutputFolder(String outputDirPath, IWindow window)
if (!outputDir.canWrite()) {
logger.warn("The output folder is not writable. path = {}", outputDir.getAbsolutePath());
JOptionPane.showMessageDialog(window.getParent(),
Messages.getMessage("message.not_writable_output_folder", outputDir.getAbsolutePath()),
Messages.getMessage("message.not_writable_output_folder", outputDir.getAbsolutePath()),
Messages.getMessage("title.not_writable_output_folder"),
JOptionPane.WARNING_MESSAGE);
return false;
Expand All @@ -136,8 +139,8 @@ private String getOutputDirPath(IWindow window, ProjectAccessor projectAccessor)
JFileChooser fileChooser = new JFileChooser();
fileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
fileChooser.setDialogTitle(Messages.getMessage("title.choose_output_dir"));
File projectDir = new File(projectAccessor.getProjectPath()).getParentFile();

File projectDir = new File(projectAccessor.getProjectPath()).getParentFile();
if (projectDir != null && projectDir.exists() && projectDir.canWrite()) {
fileChooser.setSelectedFile(projectDir);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

public class GenerateGoogleMockAction extends GenerateCodeAction {
@Override
protected void generateCode(AbstractCModule cModule, String outputDirPath) throws IOException {
protected void generateCode(AbstractCModule cModule, String outputDirPath) throws IOException, InterruptedException {
GoogleMockGenerator googleMockGenerator = new GoogleMockGenerator(cModule);
googleMockGenerator.outputHeader(outputDirPath);
googleMockGenerator.outputSource(outputDirPath);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.change_vision.astah.extension.plugin.uml2c.astahutil;

import com.change_vision.jude.api.inf.AstahAPI;

public class AstahUtil {
public static String getFullPathOfConfigDir() {
String edition;
try {
edition = AstahAPI.getAstahAPI().getProjectAccessor().getAstahEdition();
} catch (ClassNotFoundException e) {
e.printStackTrace();
return "";
}
String userHomeDir = System.getProperty("user.home");
return userHomeDir + "/.astah/" + edition;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package com.change_vision.astah.extension.plugin.uml2c.codeformatter;

import java.io.File;
import java.io.IOException;

import java.lang.InterruptedException;
import java.lang.ProcessBuilder;
import java.lang.Process;

import javax.management.RuntimeErrorException;

import com.change_vision.astah.extension.plugin.uml2c.astahutil.AstahUtil;

public class CodeFormatter {

public static void format(String codePath) throws IOException, InterruptedException {
if (!hasUncrustify()) {
return;
}

ProcessBuilder pb = new ProcessBuilder(
getUncrustifyExePath(),
"-c", getUncrustifyCfgPath(),
"-f", codePath,
"-o", codePath);

Process process = pb.start();
int procRet = process.waitFor();
if (procRet != 0) {
throw new RuntimeErrorException(new Error("Uncrustify fails: " + String.valueOf(procRet)));
}

// Cleanup temporary files.
new File(codePath + ".unc-backup.md5~").delete();
new File(codePath + ".unc-backup~").delete();
}

private static boolean hasUncrustify() {
String astahConfigPath = AstahUtil.getFullPathOfConfigDir();

File exeFile = new File(getUncrustifyExePath());
if (!exeFile.exists()) {
return false;
}

File cfgFile = new File(getUncrustifyCfgPath());
if (!cfgFile.exists()) {
return false;
}

return true;
}

private static String getUncrustifyExePath() {
return AstahUtil.getFullPathOfConfigDir() + "/plugins/uml2c/uncrustify/uncrustify.exe";
};

private static String getUncrustifyCfgPath() {
return AstahUtil.getFullPathOfConfigDir() + "/plugins/uml2c/uncrustify/custom.cfg";
};
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,19 +10,19 @@ public CSkeletonGenerator(AbstractCModule cModule) {
this.codeGenerator = new CodeGenerator(cModule);
}

public void outputHeader(String dirPath) throws IOException {
public void outputHeader(String dirPath) throws IOException, InterruptedException {
String codePath = dirPath + "/" + codeGenerator.getCModuleName() + ".h";
String templatePath = codeGenerator.getTemplateDirPath() + "header.vm";
codeGenerator.outputCode(codePath, templatePath);
}

public void outputPrivateHeader(String dirPath) throws IOException {
public void outputPrivateHeader(String dirPath) throws IOException, InterruptedException {
String codePath = dirPath + "/" + codeGenerator.getCModuleName() + "Private.h";
String templatePath = codeGenerator.getTemplateDirPath() + "private-header.vm";
codeGenerator.outputCode(codePath, templatePath);
}

public void outputSource(String dirPath) throws IOException {
public void outputSource(String dirPath) throws IOException, InterruptedException {
String codePath = dirPath + "/" + codeGenerator.getCModuleName() + ".c";
String templatePath = codeGenerator.getTemplateDirPath() + "source.vm";
codeGenerator.outputCode(codePath, templatePath);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,24 @@
import java.io.OutputStreamWriter;
import java.io.PrintWriter;

import java.lang.InterruptedException;

import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.Velocity;
import org.apache.velocity.exception.ResourceNotFoundException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.change_vision.astah.extension.plugin.uml2c.codeformatter.CodeFormatter;
import com.change_vision.astah.extension.plugin.uml2c.astahutil.AstahUtil;
import com.change_vision.astah.extension.plugin.uml2c.cmodule.AbstractCModule;
import com.change_vision.jude.api.inf.AstahAPI;


public class CodeGenerator {
private static final String TEMPLATE_ENCODING = "UTF-8"; //"UTF-8", "Windows-31J"
private static final String OUTPUT_ENCODING = "UTF-8"; //"UTF-8", "Windows-31J"
private static final String templateDirPath = "plugins/uml2c/";
private static final String TEMPLATE_DIR_PATH = "plugins/uml2c/";
private static Logger logger = LoggerFactory.getLogger(CodeGenerator.class);
private AbstractCModule cModule;

Expand All @@ -33,7 +37,7 @@ public CodeGenerator(AbstractCModule cModule) {
Velocity.init();
}

public void outputCode(String codePath, String templatePath) throws IOException {
public void outputCode(String codePath, String templatePath) throws IOException, InterruptedException {
VelocityContext context = new VelocityContext();
context.put("cModule", cModule);

Expand All @@ -43,36 +47,26 @@ public void outputCode(String codePath, String templatePath) throws IOException
} catch (ResourceNotFoundException e) {
throw e;
}

File file = new File(codePath);
logger.info("Generating {} ({})", file.getName(), templatePath);

PrintWriter pw = new PrintWriter(new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file), OUTPUT_ENCODING)));
template.merge(context, pw);
pw.close();

CodeFormatter.format(codePath);
}

public String getCModuleName() {
return cModule.getName();
}

public String getTemplateSearchDirPath() {
return getAstahConfigPath() + ",.";
}

public static String getAstahConfigPath() {
String edition;
try {
edition = AstahAPI.getAstahAPI().getProjectAccessor().getAstahEdition();
} catch (ClassNotFoundException e) {
e.printStackTrace();
return "";
}
String userHomeDir = System.getProperty("user.home");
return userHomeDir + "/.astah/" + edition;
return AstahUtil.getFullPathOfConfigDir() + ",.";
}

public String getTemplateDirPath() {
return templateDirPath;
return TEMPLATE_DIR_PATH;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,13 @@ public GoogleMockGenerator(AbstractCModule cModule) {
this.codeGenerator = new CodeGenerator(cModule);
}

public void outputHeader(String dirPath) throws IOException {
public void outputHeader(String dirPath) throws IOException, InterruptedException {
String codePath = dirPath + "/Mock_" + codeGenerator.getCModuleName() + ".h";
String templatePath = codeGenerator.getTemplateDirPath() + "mock-header.vm";
codeGenerator.outputCode(codePath, templatePath);
}

public void outputSource(String dirPath) throws IOException {
public void outputSource(String dirPath) throws IOException, InterruptedException {
String codePath = dirPath + "/Mock_" + codeGenerator.getCModuleName() + ".cpp";
String templatePath = codeGenerator.getTemplateDirPath() + "mock-source.vm";
codeGenerator.outputCode(codePath, templatePath);
Expand Down