【Ant】 Antビルドにより、CSVファイルからEnumクラスを自動生成する

■ やりたいこと

Antビルドすると・・・

1) CSVファイルを記載された内容をEnumとするソースをキックし、Javaソースを自動生成
2) そのJavaファイル群を共有機能プロジェクト Common 内に移動
3) その共有機能プロジェクト Common をJar化

後日談

 * Java の Pluggable Annotation Processing APIを使用して、
   プロパティファイルからEnumクラスを生成するってのができるらしい
http://vermeer.hatenablog.jp/entry/2017/11/16/170859

■ プロジェクト構成

 * 共有機能プロジェクト Common
   + CSVファイル
 * 対象プロジェクト Main(共有機能プロジェクト Commonを使用する側)
    <= Commonに依存している

■ Antビルドで行う手順

1) CSVファイルを取り込む
2) ソース(Enum)を自動生成
3) 自動生成ソースを、共有機能プロジェクト Common に移動
4) 共有機能プロジェクト Common のJar作成

■ サンプル

build.xml

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<project basedir="." default="createJar" name="Common">
  <property name="JarName" value="Common" />
  <target name="init" description="初期化">
    <property name="class.path" value="./class" />
    <delete dir="${class.path}"/>
    <mkdir dir="${class.path}"/>
    <property name="target" value="csv" />
    <fileset id="csvfiles" dir=".">
       <include name="${target}/*.csv" />
    </fileset>
    <property name="targetfiles" refid="csvfiles"/>
  </target>
  <target name="compile" depends="init" description="compiles">
    <javac srcdir="./src" destdir="./class" encoding="MS932"/>
  </target>
  <target name="exec" depends="compile" description="Enum">
    <echo message="execute Java" />
    <java classname="com.support.EnumCreator" classpath="${class.path}" >
        <arg value="${targetfiles}"/>
    </java>
    <antcall target="moveJavaFile">
      <param name="copyFrom" value="./csv"/>
      <param name="copyTo" value="./src/com/enums"/>
    </antcall>
    <antcall target="compile" />
  </target>
  <target name="moveJavaFile" description="Enum">
    <copy todir="${copyTo}" overwrite="true">
       <fileset dir="${copyFrom}" includes="**/*.java" excludes="**/*.csv" />
    </copy>
    <delete>
      <fileset dir="${copyFrom}" includes="**/*.java" excludes="**/*.csv" />
    </delete>
  </target>
   <target name="createJar" depends="exec">
      <jar destfile="${JarName}.jar" 
           basedir="." 
           includes="**/*.class" >
      </jar>
   </target>
</project>

EnumCreator.java

CSVからEnumを生成するプログラム
package com.support;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;

public class EnumCreator {
   private static final String Delimiter = ";";

   public static void main(String[] args) {
      if (args == null || args.length == 0) {
         System.out.println("args is empty");
         return;
      }
      System.out.println("args[0] is " + args[0]);
      String[] targetFiles = args[0].split(EnumCreator.Delimiter, -1);
      for (String targetFile : targetFiles) {
         EnumCreator.createEnumFile(targetFile.trim());
      }
   }

   private static void createEnumFile(String targetFile) {
      String outoutFileName = targetFile.replace(".csv", ".java");
      System.out.println("outoutfileName " + outoutFileName);
      File outoutFile = new File(outoutFileName);
      try (FileOutputStream fileOutputStream = 
            new FileOutputStream(outoutFile);
            OutputStreamWriter outputStreamWriter = 
                  new OutputStreamWriter(fileOutputStream, "UTF-8");
            PrintWriter printWriter = new PrintWriter(outputStreamWriter);) {
         printWriter.println(String.format("package %s;", "com.enums"));
         printWriter.println("");
         String enumName = removeFileExtension(outoutFile.getName());
         printWriter.println(String.format("public enum %s {", enumName));
         List<List<String>> csvValues = EnumCreator.getCsvValues(targetFile);
         for (List<String> values : csvValues) {
            System.out.println("values.get(0) " + values.get(0));
            printWriter.println(String.format("   %s,", values.get(0)));
         }
         printWriter.println("}");
      } catch (Exception ex) {
         ex.printStackTrace();
      }
   }

   private static List<List<String>> getCsvValues(String fileName) {
      List<List<String>> returnValues = new ArrayList<List<String>>();
      try (BufferedReader bufferedReader = new BufferedReader(new FileReader(
            new File(fileName)))) {
         // 最終行まで読み込む
         String line = "";
         while ((line = bufferedReader.readLine()) != null) {
            List<String> values = new ArrayList<String>();
            // 1行をデータの要素に分割
            StringTokenizer stringTokenizer = new StringTokenizer(line, ",");
            while (stringTokenizer.hasMoreTokens()) {
               // 1行の各要素を追加
               values.add(stringTokenizer.nextToken());
            }
            returnValues.add(values);
         }
      } catch (Exception ex) {
         ex.printStackTrace();
      }
      return returnValues;
   }
   private static String removeFileExtension(String fileName) {
      int lastDotPosition = fileName.lastIndexOf('.');

      if (lastDotPosition == -1) {
        return fileName;
      } else if (lastDotPosition == 0) {
        return fileName;
      } else {
        return fileName.substring(0, lastDotPosition);
      }
    }
}

CSVファイル

Operation.csv
Error
Success
Sex.csv
Male
Female

関連記事

CSVをパースするプログラム
http://blogs.yahoo.co.jp/dk521123/33910085.html
Ant で、Javaコンパイル / Javaの実行 を行うサンプル
http://blogs.yahoo.co.jp/dk521123/33973954.html
Ant で、Javaコンパイル / JARファイル作成 を行うサンプル
http://blogs.yahoo.co.jp/dk521123/34019895.html
ファイル・ディレクトリを扱う
http://blogs.yahoo.co.jp/dk521123/33994078.html
他から呼び出す(antcall)
http://blogs.yahoo.co.jp/dk521123/33998079.html
Pluggable Annotation Processing API
https://blogs.yahoo.co.jp/dk521123/37774601.html