基於Freemarker的eclipse plugin代碼生成器插件開發



基於Freemarker的eclipse plugin代碼生成器插件開發

固定類型的軟件寫多了,裏面總是有一些複製粘貼改變類名改變量的基礎文件,相似程度非常高。作爲一名程序員,堅持不多寫一行重複代碼的精神,寫了一個Eclipse的代碼生成器插件。插件通過在xml文件中配置的變量信息及模版位置、目標文件位置信息,直接生成目標文件,減少了大量的重複工作。

1.建立一個plug-in with a popup menu工程,引入freemarker.jar,配置popup menu的對應文件擴展名爲.coding.xml

2.先寫核心的文檔生成代碼,保證使用main函數可調用。核心的內容是按照freemarker的要求寫好 模版路徑、模板文件名、目標文件路徑、目標文件名、文件所使用的字符集、以及包含所有數據的map

 1 public class CodegenUtil
 2 {
 3   public static void genFile(String templatePath, String templateFileName, String targetPath, String targetFileName, String charset, Map paramMap)
 4     throws IOException, TemplateException
 5   {
 6    
 7     File localFile = new File(targetPath, targetFileName);
 8     if (!localFile.exists()) {
 9       if (!localFile.getParentFile().exists())
10         localFile.getParentFile().mkdirs();
11       localFile.createNewFile();
12     }
13     OutputStreamWriter localOutputStreamWriter = new OutputStreamWriter(new FileOutputStream(localFile), charset);
14 
15     Configuration freemarkerConfigration = new Configuration();
16     freemarkerConfigration.setDirectoryForTemplateLoading(new File(templatePath));
17 
18     Template localTemplate = freemarkerConfigration.getTemplate(templateFileName, charset);
19     localTemplate.process(paramMap, localOutputStreamWriter);
20     localOutputStreamWriter.close();
21     
22   }
23 }

3.寫Action調用

public void run(IAction action) {		
    
    //讀取選定的配置文件	
    IStructuredSelection selection =(IStructuredSelection) this.selection;		

    ConsoleFactory.printToConsole("--------Start Coding--------", true);
    
    for(Object element:selection.toList()){
      File file = (File)element;	
      String fullpath = file.getLocationURI().getPath();
      
      Map<String, String> params;
      List<Map<String,String>>  templateMapList=new ArrayList<Map<String,String>>(); 
      
      try {

        String configfilepath=fullpath.substring(1);
        ConsoleFactory.printToConsole("...load coding config "+configfilepath, true);
        
        params = XmlUtil.getVars(configfilepath);
        templateMapList=XmlUtil.getTemplates(configfilepath);
        
        for(Map<String ,String > templateMap:templateMapList){
          String templateFilePath=templateMap.get(XmlUtil.TEMPLATE_PATH);
          String templateFileName=templateMap.get(XmlUtil.TEMPLATE_NAME);
          String targetFilePath=templateMap.get(XmlUtil.TARGET_PATH);
          String targetFileName=templateMap.get(XmlUtil.TARGET_NAME);
          
          ConsoleFactory.printToConsole("... ... coding ... "+targetFilePath+"\\"+targetFileName, true);

          params.put(XmlUtil.TEMPLATE_PATH, templateFilePath);
          params.put(XmlUtil.TEMPLATE_NAME, templateFileName);
          params.put(XmlUtil.TARGET_PATH, targetFilePath);
          params.put(XmlUtil.TARGET_NAME, targetFileName);					
          
          String charset=params.get(XmlUtil.CHARSET);	
          
          CodegenUtil.genFile(templateFilePath,templateFileName,targetFilePath,targetFileName,charset,params);		

        }			
        
      } catch (Exception e) {
        e.printStackTrace();
      }		
    }

    ConsoleFactory.printToConsole("--------Finish Coding--------", true);
    
  }

4.使用System.out.print所打印的東西在插件的運行環境下是不顯示的,ConsoleFactory是我寫的一個控制檯輸出類,調用了Eclipse的控制檯,主要用來在使用時給出相關的代碼生成提示。

public class ConsoleFactory implements IConsoleFactory {

  private static MessageConsole console=new MessageConsole("",null);
  static boolean exists=false;
  
  @Override
  public void openConsole() {
    showConsole();
  }
  
  private static void showConsole(){
    if(console!=null){
      IConsoleManager manager=ConsolePlugin.getDefault().getConsoleManager();
      IConsole[] existing = manager.getConsoles();
      
      exists=false;
      for(int i=0;i<existing.length;i++){
        if(console==existing[i]){
          exists=true;
        }
      }
      if(!exists){
        manager.addConsoles(new IConsole[]{console});
      }
      
    }
  }
  
  public static void closeConsole(){
    IConsoleManager manager = ConsolePlugin.getDefault().getConsoleManager();
    if(console!=null){
      manager.removeConsoles(new IConsole[]{console});			
    }
  }
  
  public static MessageConsole getConsole(){
    showConsole();
    return console;
  }
  
  public static void printToConsole(String message , boolean activate){
    MessageConsoleStream printer = ConsoleFactory.getConsole().newMessageStream();
    printer.setActivateOnWrite(activate);
    printer.println(message);
  }

}

5.主要內容完畢。使用時先配好xml文件,如下示例。在Eclipse中選中.coding.xml文件,右鍵菜單 [代碼生成器]-->[生成代碼]

<?xml version="1.0" encoding="utf-8" ?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <variables>
    <variable name="developer" value="PennPeng" />
    <variable name="charset" value="utf-8" />		
    <variable name="class" value="CodeGen" />
    <variable name="name" value="姓名" />
    <variable name="age" value="年齡" />
  </variables>
  
  <templates>
    <template>			
      <variable name="templatepath" value="E:\CodeGenTest\template" />
      <variable name="templatename" value="a.ftl" />
      <variable name="targetpath" value="E:\CodeGenTest" />		
      <variable name="targetname" value="CodeGen.java" />
    </template>
    <template>			
      <variable name="templatepath" value="E:\CodeGenTest\template" />
      <variable name="templatename" value="b.ftl" />
      <variable name="targetpath" value="E:\CodeGenTest" />		
      <variable name="targetname" value="CodeGen2.java" />
    </template>
  </templates>
</config>

還有很多需要擴展完善的地方,比如數據庫的自動支持、各類型文檔的生成。

項目地址 https://github.com/buaawp/codegen

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章