XlsMapper.java

  1. package com.gh.mygreen.xlsmapper;

  2. import java.io.IOException;
  3. import java.io.InputStream;
  4. import java.io.OutputStream;

  5. import com.gh.mygreen.xlsmapper.annotation.XlsColumn;
  6. import com.gh.mygreen.xlsmapper.annotation.XlsDateTimeConverter;
  7. import com.gh.mygreen.xlsmapper.annotation.XlsHorizontalRecords;
  8. import com.gh.mygreen.xlsmapper.annotation.XlsLabelledCell;
  9. import com.gh.mygreen.xlsmapper.annotation.XlsRecordOption;
  10. import com.gh.mygreen.xlsmapper.annotation.XlsRecordOption.OverOperation;
  11. import com.gh.mygreen.xlsmapper.annotation.XlsSheet;
  12. import com.gh.mygreen.xlsmapper.validation.MultipleSheetBindingErrors;
  13. import com.gh.mygreen.xlsmapper.validation.SheetBindingErrors;


  14. /**
  15.  * ExcelのシートとJavaオブジェクトをマッピングする機能を提供する。
  16.  *
  17.  * <h3 class="description">マッピングの基本</h3>
  18.  * <p>次のような表のExcelシートをマッピングする例を説明します。</p>
  19.  *
  20.  * <div class="picture">
  21.  *    <img src="doc-files/howto_load.png" alt="">
  22.  *    <p>基本的なマッピング</p>
  23.  * </div>
  24.  *
  25.  * <p>まず、シート1つに対して、POJOクラスを作成します。</p>
  26.  * <ul>
  27.  *   <li>シート名を指定するために、アノテーション {@link XlsSheet} をクラスに付与します。</li>
  28.  *   <li>見出し付きのセル「Date」をマッピングするフィールドに、アノテーション {@link XlsLabelledCell} に付与します。</li>
  29.  *   <li>表「User List」をマッピングするListのフィールドに、アノテーション {@link XlsHorizontalRecords} を付与します。</li>
  30.  * </ul>
  31.  *
  32.  *
  33.  * <pre class="highlight"><code class="java">
  34.  * // シート用のPOJOクラスの定義
  35.  * {@literal @XlsSheet(name="List")}
  36.  * public class UserSheet {
  37.  *
  38.  *     {@literal @XlsLabelledCell(label="Date", type=LabelledCellType.Right)}
  39.  *     Date createDate;
  40.  *
  41.  *     {@literal @XlsHorizontalRecords(tableLabel="User List")}
  42.  *     {@literal List<UserRecord>} users;
  43.  *
  44.  * }
  45.  * </code></pre>
  46.  *
  47.  *
  48.  * <p>続いて、表「User List」の1レコードをマッピングするための、POJOクラスを作成します。</p>
  49.  * <ul>
  50.  *   <li>レコードの列をマッピングするために、アノテーション {@link XlsColumn} をフィールドに付与します。</li>
  51.  *   <li>フィールドのクラスタイプが、intや列挙型の場合もマッピングできます。</li>
  52.  * </ul>
  53.  *
  54.  * <pre class="highlight"><code class="java">
  55.  * // レコード用のPOJOクラスの定義
  56.  * public class UserRecord {
  57.  *
  58.  *     {@literal @XlsColumn(columnName="ID")}
  59.  *     int no;
  60.  *
  61.  *     {@literal @XlsColumn(columnName="Class", merged=true)}
  62.  *     String className;
  63.  *
  64.  *     {@literal @XlsColumn(columnName="Name")}
  65.  *     String name;
  66.  *
  67.  *     {@literal @XlsColumn(columnName="Gender")}
  68.  *     Gender gender;
  69.  *
  70.  * }
  71.  *
  72.  * // 性別を表す列挙型の定義
  73.  * public enum Gender {
  74.  *    male, female;
  75.  * }
  76.  * </code></pre>
  77.  *
  78.  *
  79.  * <p>作成したPOJOを使ってシートを読み込むときは、XlsMapper#load メソッドを利用します。</p>
  80.  *
  81.  * <pre class="highlight"><code class="java">
  82.  * // シートの読み込み
  83.  * XlsMapper xlsMapper = new XlsMapper();
  84.  * UserSheet sheet = xlsMapper.load(
  85.  *         new FileInputStream("example.xls"), // 読み込むExcelファイル。
  86.  *         UserSheet.class                     // シートマッピング用のPOJOクラス。
  87.  *   );
  88.  * </code></pre>
  89.  *
  90.  *
  91.  * <h3 class="description">書き込み方の基本</h3>
  92.  * <p>同じシートの形式を使って、書き込み方を説明します。
  93.  *   <br>まず、書き込み先のテンプレートとなるExcelシートを用意します。 レコードなどは空を設定します。
  94.  * </p>
  95.  *
  96.  * <div class="picture">
  97.  *    <img src="doc-files/howto_save.png" alt="">
  98.  *    <p>データが空のテンプレートファイル</p>
  99.  * </div>
  100.  *
  101.  * <p>続いて、読み込み時に作成したシート用のマッピングクラスに、書き込み時の設定を付け加えるために修正します。</p>
  102.  * <ul>
  103.  *   <li>セル「Date」の書き込み時の書式を指定するために、アノテーション {@link XlsDateTimeConverter} に付与します。
  104.  *     <br>属性 {@link XlsDateTimeConverter#excelPattern()} でExcelのセルの書式を設定します。
  105.  *   </li>
  106.  *   <li>表「User List」のレコードを追加する操作を指定するために、アノテーションの属性 {@link XlsRecordOption#overOperation()}を指定します。
  107.  *     <br>テンプレート上は、レコードが1行分しかないですが、実際に書き込むレコード数が2つ以上の場合、足りなくなるため、その際のシートの操作方法を指定します。
  108.  *     <br>今回の{@link OverOperation#Insert}は、行の挿入を行います。
  109.  *   </li>
  110.  * </ul>
  111.  *
  112.  * <pre class="highlight"><code class="java">
  113.  * // シート用のPOJOクラスの定義
  114.  * {@literal @XlsSheet(name="List")}
  115.  * public class UserSheet {
  116.  *
  117.  *     {@literal @XlsLabelledCell(label="Date", type=LabelledCellType.Right)}
  118.  *     {@literal @XlsDateTimeConverter(excelPattern="yyyy/m/d")}
  119.  *     Date createDate;
  120.  *
  121.  *     {@literal @XlsHorizontalRecords(tableLabel="User List")}
  122.  *     {@literal @XlsRecordOperation(overCase=OverOperation#Insert)}
  123.  *     {@literal List<UserRecord>} users;
  124.  *
  125.  * }
  126.  * </code></pre>
  127.  *
  128.  * <p>修正したPOJOを使ってシートを書き込むときは、 XlsMapper#save メソッドを利用します。</p>
  129.  *
  130.  * <pre class="highlight"><code class="java">
  131.  * // 書き込むシート情報の作成
  132.  * UserSheet sheet = new UserSheet();
  133.  * sheet.createDate = new Date();
  134.  *
  135.  * {@literal List<UserRecord>} users = new {@literal ArrayList<>}();
  136.  *
  137.  * // 1レコード分の作成
  138.  * UserRecord record1 = new UserRecord();
  139.  * record1.no = 1;
  140.  * record1.className = "A";
  141.  * record1.name = "Ichiro";
  142.  * record1.gender = Gender.male;
  143.  * users.add(record1);
  144.  *
  145.  * UserRecord record2 = new UserRecord();
  146.  * // ... 省略
  147.  * users.add(record2);
  148.  *
  149.  * sheet.users = users;
  150.  *
  151.  * // シートの書き込み
  152.  * XlsMapper xlsMapper = new XlsMapper();
  153.  * xlsMapper.save(
  154.  *     new FileInputStream("template.xls"), // テンプレートのExcelファイル
  155.  *     new FileOutputStream("out.xls"),     // 書き込むExcelファイル
  156.  *     sheet                                // 作成したデータ
  157.  *     );
  158.  * </code></pre>
  159.  *
  160.  * @version 2.0
  161.  * @author T.TSUCHIE
  162.  *
  163.  */
  164. public class XlsMapper {

  165.     private Configuration configuration;

  166.     private XlsLoader loader;

  167.     private XlsSaver saver;

  168.     /**
  169.      * デフォルトコンストラクタ
  170.      */
  171.     public XlsMapper() {
  172.         this.configuration = new Configuration();
  173.         this.loader = new XlsLoader(getConfiguration());
  174.         this.saver = new XlsSaver(getConfiguration());
  175.     }

  176.     /**
  177.      * システム情報を取得します。
  178.      * @return 現在のシステム情報
  179.      */
  180.     public Configuration getConfiguration() {
  181.         return configuration;
  182.     }

  183.     /**
  184.      * システム情報を設定します。
  185.      * @param configuration システム情報
  186.      */
  187.     public void setConfiguration(Configuration configuration) {
  188.         this.configuration = configuration;
  189.         getLoader().setConfiguration(configuration);
  190.         getSaver().setConfiguration(configuration);
  191.     }

  192.     /**
  193.      * 読み込み用クラスを取得します。
  194.      * @return 読み込み用クラス
  195.      */
  196.     public XlsLoader getLoader() {
  197.         return loader;
  198.     }

  199.     /**
  200.      * 保存用クラスを取得します。
  201.      * @return 保存用クラス。
  202.      */
  203.     public XlsSaver getSaver() {
  204.         return saver;
  205.     }

  206.     /**
  207.      * Excelファイルの1シートを読み込み、任意のクラスにマッピングする。
  208.      *
  209.      * @param <P> シートをマッピングするクラスタイプ
  210.      * @param xlsIn 読み込みもとのExcelファイルのストリーム。
  211.      * @param clazz マッピング先のクラスタイプ。
  212.      * @return シートをマッピングしたオブジェクト。
  213.      *         {@link Configuration#isIgnoreSheetNotFound()}の値がtrueで、シートが見つからない場合、nullを返します。
  214.      * @throws IllegalArgumentException {@literal xlsIn == null or clazz == null}
  215.      * @throws XlsMapperException Excelファイルのマッピングに失敗した場合
  216.      * @throws IOException ファイルの読み込みに失敗した場合
  217.      *
  218.      */
  219.     public <P> P load(final InputStream xlsIn, final Class<P> clazz) throws XlsMapperException, IOException {
  220.         return loader.load(xlsIn, clazz);
  221.     }

  222.     /**
  223.      * Excelファイルの1シートを読み込み、任意のクラスにマッピングする。
  224.      *
  225.      * @param <P> シートをマッピングするクラスタイプ
  226.      * @param xlsIn 読み込みもとのExcelファイルのストリーム。
  227.      * @param clazz マッピング先のクラスタイプ。
  228.      * @return シートのマッピング結果。
  229.      *         {@link Configuration#isIgnoreSheetNotFound()}の値がtrueで、シートが見つからない場合、nullを返します。
  230.      * @throws IllegalArgumentException {@literal xlsIn == null or clazz == null}
  231.      * @throws XlsMapperException Excelファイルのマッピングに失敗した場合
  232.      * @throws IOException ファイルの読み込みに失敗した場合
  233.      */
  234.     public <P> SheetBindingErrors<P> loadDetail(final InputStream xlsIn, final Class<P> clazz) throws XlsMapperException, IOException {
  235.         return loader.loadDetail(xlsIn, clazz);
  236.     }

  237.     /**
  238.      * Excelファイルの複数シートを読み込み、任意のクラスにマップする。
  239.      * <p>{@link XlsSheet#regex()}により、複数のシートが同じ形式で、同じクラスにマッピングすする際に使用します。</p>
  240.      *
  241.      * @param xlsIn 読み込み元のExcelファイルのストリーム。
  242.      * @param clazz マッピング先のクラスタイプ。
  243.      * @return マッピングした複数のシート。
  244.      *         {@link Configuration#isIgnoreSheetNotFound()}の値がtrueで、シートが見つからない場合、マッピング結果には含まれません。
  245.      * @throws IllegalArgumentException {@literal xlsIn == null or clazz == null}
  246.      * @throws XlsMapperException マッピングに失敗した場合
  247.      * @throws IOException ファイルの読み込みに失敗した場合
  248.      */
  249.     public <P> P[] loadMultiple(final InputStream xlsIn, final Class<P> clazz) throws XlsMapperException, IOException {
  250.         return loader.loadMultiple(xlsIn, clazz);
  251.     }

  252.     /**
  253.      * XMLによるマッピングを指定し、Excelファイルの複数シートを読み込み、任意のクラスにマップする。
  254.      * <p>{@link XlsSheet#regex()}により、複数のシートが同じ形式で、同じクラスにマッピングすする際に使用します。</p>
  255.      *
  256.      * @param <P> シートをマッピングするクラスタイプ
  257.      * @param xlsIn 読み込み元のExcelファイルのストリーム。
  258.      * @param clazz マッピング先のクラスタイプ。
  259.      * @return 複数のシートのマッピング結果。
  260.      *         {@link Configuration#isIgnoreSheetNotFound()}の値がtrueで、シートが見つからない場合、マッピング結果には含まれません。
  261.      * @throws IllegalArgumentException {@literal xlsIn == null or clazz == null}
  262.      * @throws XlsMapperException マッピングに失敗した場合
  263.      * @throws IOException ファイルの読み込みに失敗した場合
  264.      */
  265.     public <P> MultipleSheetBindingErrors<P> loadMultipleDetail(final InputStream xlsIn, final Class<P> clazz)
  266.             throws XlsMapperException, IOException {
  267.         return loader.loadMultipleDetail(xlsIn, clazz);
  268.     }

  269.     /**
  270.      * Excelファイルの複数シートを読み込み、任意のクラスにマップする。
  271.      * <p>複数のシートの形式を一度に読み込む際に使用します。</p>
  272.      *
  273.      * @param xlsIn 読み込み元のExcelファイルのストリーム。
  274.      * @param classes マッピング先のクラスタイプの配列。
  275.      * @return マッピングした複数のシート。
  276.      *         {@link Configuration#isIgnoreSheetNotFound()}の値がtrueで、シートが見つからない場合、マッピング結果には含まれません。
  277.      * @throws IllegalArgumentException {@literal xlsIn == null or classes == null}
  278.      * @throws IllegalArgumentException {@literal calsses.length == 0}
  279.      * @throws XlsMapperException マッピングに失敗した場合
  280.      * @throws IOException ファイルの読み込みに失敗した場合
  281.      */
  282.     public Object[] loadMultiple(final InputStream xlsIn, final Class<?>[] classes) throws XlsMapperException, IOException {
  283.         return loader.loadMultiple(xlsIn, classes);
  284.     }

  285.     /**
  286.      * Excelファイルの複数シートを読み込み、任意のクラスにマップする。
  287.      * <p>複数のシートの形式を一度に読み込む際に使用します。</p>
  288.      *
  289.      * @param xlsIn 読み込み元のExcelファイルのストリーム。
  290.      * @param classes マッピング先のクラスタイプの配列。
  291.      * @return マッピングした複数のシートの結果。
  292.      *         {@link Configuration#isIgnoreSheetNotFound()}の値がtrueで、シートが見つからない場合、マッピング結果には含まれません。
  293.      * @throws IllegalArgumentException {@literal xlsIn == null or classes == null}
  294.      * @throws IllegalArgumentException {@literal calsses.length == 0}
  295.      * @throws IOException ファイルの読み込みに失敗した場合
  296.      * @throws XlsMapperException マッピングに失敗した場合
  297.      */
  298.     public MultipleSheetBindingErrors<Object> loadMultipleDetail(final InputStream xlsIn, final Class<?>[] classes)
  299.             throws XlsMapperException, IOException {
  300.         return loader.loadMultipleDetail(xlsIn, classes);
  301.     }

  302.     /**
  303.      * JavaのオブジェクトをExeclファイルに出力する。
  304.      * <p>出力するファイルは、引数で指定した雛形となるテンプレート用のExcelファイルをもとに出力する。</p>
  305.      *
  306.      * @param templateXlsIn 雛形となるExcelファイルの入力
  307.      * @param xlsOut 出力先のストリーム
  308.      * @param beanObj 書き込むBeanオブジェクト
  309.      * @throws IllegalArgumentException {@literal templateXlsIn == null or xlsOut == null or beanObj == null}
  310.      * @throws XlsMapperException マッピングに失敗した場合
  311.      * @throws IOException テンプレートのファイルの読み込みやファイルの出力に失敗した場合
  312.      */
  313.     public void save(final InputStream templateXlsIn, final OutputStream xlsOut, final Object beanObj) throws XlsMapperException, IOException {
  314.         saver.save(templateXlsIn, xlsOut, beanObj);
  315.     }

  316.     /**
  317.      * JavaのオブジェクトをExeclファイルに出力する。
  318.      * <p>出力するファイルは、引数で指定した雛形となるテンプレート用のExcelファイルをもとに出力する。</p>
  319.      *
  320.      * @param <P> マッピング対象のクラスタイプ
  321.      * @param templateXlsIn 雛形となるExcelファイルの入力
  322.      * @param xlsOut 出力先のストリーム
  323.      * @param beanObjs 書き込むBeanオブジェクト
  324.      * @return マッピング結果。
  325.      *         {@link Configuration#isIgnoreSheetNotFound()}の値がtrueで、シートが見つからない場合、nullを返します。
  326.      * @throws IllegalArgumentException {@literal templateXlsIn == null or xlsOut == null or beanObj == null}
  327.      * @throws XlsMapperException マッピングに失敗した場合
  328.      * @throws IOException テンプレートのファイルの読み込みやファイルの出力に失敗した場合
  329.      */
  330.     public <P> SheetBindingErrors<P> saveDetail(final InputStream templateXlsIn, final OutputStream xlsOut, final P beanObjs) throws XlsMapperException, IOException {
  331.         return saver.saveDetail(templateXlsIn, xlsOut, beanObjs);
  332.     }

  333.     /**
  334.      * 複数のオブジェクトをそれぞれのシートへ保存する。
  335.      * @param templateXlsIn 雛形となるExcelファイルの入力
  336.      * @param xlsOut xlsOut 出力先のストリーム
  337.      * @param beanObj 書き込むオブジェクトの配列。
  338.      * @throws IllegalArgumentException {@literal templateXlsIn == null or xlsOut == null or beanObjs == null}
  339.      * @throws IllegalArgumentException {@literal }
  340.      * @throws XlsMapperException マッピングに失敗した場合
  341.      * @throws IOException テンプレートのファイルの読み込みやファイルの出力に失敗した場合
  342.      */
  343.     public void saveMultiple(final InputStream templateXlsIn, final OutputStream xlsOut, final Object[] beanObj) throws XlsMapperException, IOException {
  344.         saver.saveMultiple(templateXlsIn, xlsOut, beanObj);
  345.     }

  346.     /**
  347.      * 複数のオブジェクトをそれぞれのシートへ保存する。
  348.      * @param templateXlsIn 雛形となるExcelファイルの入力
  349.      * @param xlsOut xlsOut 出力先のストリーム
  350.      * @param beanObjs 書き込むオブジェクトの配列。
  351.      * @return マッピング結果。
  352.      *         {@link Configuration#isIgnoreSheetNotFound()}の値がtrueで、シートが見つからない場合、結果に含まれません。
  353.      * @throws IllegalArgumentException {@literal templateXlsIn == null or xlsOut == null or beanObjs == null}
  354.      * @throws IllegalArgumentException {@literal }
  355.      * @throws XlsMapperException マッピングに失敗した場合
  356.      * @throws IOException テンプレートのファイルの読み込みやファイルの出力に失敗した場合
  357.      */
  358.     public MultipleSheetBindingErrors<Object> saveMultipleDetail(final InputStream templateXlsIn, final OutputStream xlsOut, final Object[] beanObjs) throws XlsMapperException, IOException {
  359.         return saver.saveMultipleDetail(templateXlsIn, xlsOut, beanObjs);
  360.     }

  361. }