XlsMapper.java
package com.gh.mygreen.xlsmapper;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import com.gh.mygreen.xlsmapper.annotation.XlsColumn;
import com.gh.mygreen.xlsmapper.annotation.XlsDateTimeConverter;
import com.gh.mygreen.xlsmapper.annotation.XlsHorizontalRecords;
import com.gh.mygreen.xlsmapper.annotation.XlsLabelledCell;
import com.gh.mygreen.xlsmapper.annotation.XlsRecordOption;
import com.gh.mygreen.xlsmapper.annotation.XlsRecordOption.OverOperation;
import com.gh.mygreen.xlsmapper.annotation.XlsSheet;
import com.gh.mygreen.xlsmapper.validation.MultipleSheetBindingErrors;
import com.gh.mygreen.xlsmapper.validation.SheetBindingErrors;
/**
* ExcelのシートとJavaオブジェクトをマッピングする機能を提供する。
*
* <h3 class="description">マッピングの基本</h3>
* <p>次のような表のExcelシートをマッピングする例を説明します。</p>
*
* <div class="picture">
* <img src="doc-files/howto_load.png" alt="">
* <p>基本的なマッピング</p>
* </div>
*
* <p>まず、シート1つに対して、POJOクラスを作成します。</p>
* <ul>
* <li>シート名を指定するために、アノテーション {@link XlsSheet} をクラスに付与します。</li>
* <li>見出し付きのセル「Date」をマッピングするフィールドに、アノテーション {@link XlsLabelledCell} に付与します。</li>
* <li>表「User List」をマッピングするListのフィールドに、アノテーション {@link XlsHorizontalRecords} を付与します。</li>
* </ul>
*
*
* <pre class="highlight"><code class="java">
* // シート用のPOJOクラスの定義
* {@literal @XlsSheet(name="List")}
* public class UserSheet {
*
* {@literal @XlsLabelledCell(label="Date", type=LabelledCellType.Right)}
* Date createDate;
*
* {@literal @XlsHorizontalRecords(tableLabel="User List")}
* {@literal List<UserRecord>} users;
*
* }
* </code></pre>
*
*
* <p>続いて、表「User List」の1レコードをマッピングするための、POJOクラスを作成します。</p>
* <ul>
* <li>レコードの列をマッピングするために、アノテーション {@link XlsColumn} をフィールドに付与します。</li>
* <li>フィールドのクラスタイプが、intや列挙型の場合もマッピングできます。</li>
* </ul>
*
* <pre class="highlight"><code class="java">
* // レコード用のPOJOクラスの定義
* public class UserRecord {
*
* {@literal @XlsColumn(columnName="ID")}
* int no;
*
* {@literal @XlsColumn(columnName="Class", merged=true)}
* String className;
*
* {@literal @XlsColumn(columnName="Name")}
* String name;
*
* {@literal @XlsColumn(columnName="Gender")}
* Gender gender;
*
* }
*
* // 性別を表す列挙型の定義
* public enum Gender {
* male, female;
* }
* </code></pre>
*
*
* <p>作成したPOJOを使ってシートを読み込むときは、XlsMapper#load メソッドを利用します。</p>
*
* <pre class="highlight"><code class="java">
* // シートの読み込み
* XlsMapper xlsMapper = new XlsMapper();
* UserSheet sheet = xlsMapper.load(
* new FileInputStream("example.xls"), // 読み込むExcelファイル。
* UserSheet.class // シートマッピング用のPOJOクラス。
* );
* </code></pre>
*
*
* <h3 class="description">書き込み方の基本</h3>
* <p>同じシートの形式を使って、書き込み方を説明します。
* <br>まず、書き込み先のテンプレートとなるExcelシートを用意します。 レコードなどは空を設定します。
* </p>
*
* <div class="picture">
* <img src="doc-files/howto_save.png" alt="">
* <p>データが空のテンプレートファイル</p>
* </div>
*
* <p>続いて、読み込み時に作成したシート用のマッピングクラスに、書き込み時の設定を付け加えるために修正します。</p>
* <ul>
* <li>セル「Date」の書き込み時の書式を指定するために、アノテーション {@link XlsDateTimeConverter} に付与します。
* <br>属性 {@link XlsDateTimeConverter#excelPattern()} でExcelのセルの書式を設定します。
* </li>
* <li>表「User List」のレコードを追加する操作を指定するために、アノテーションの属性 {@link XlsRecordOption#overOperation()}を指定します。
* <br>テンプレート上は、レコードが1行分しかないですが、実際に書き込むレコード数が2つ以上の場合、足りなくなるため、その際のシートの操作方法を指定します。
* <br>今回の{@link OverOperation#Insert}は、行の挿入を行います。
* </li>
* </ul>
*
* <pre class="highlight"><code class="java">
* // シート用のPOJOクラスの定義
* {@literal @XlsSheet(name="List")}
* public class UserSheet {
*
* {@literal @XlsLabelledCell(label="Date", type=LabelledCellType.Right)}
* {@literal @XlsDateTimeConverter(excelPattern="yyyy/m/d")}
* Date createDate;
*
* {@literal @XlsHorizontalRecords(tableLabel="User List")}
* {@literal @XlsRecordOperation(overCase=OverOperation#Insert)}
* {@literal List<UserRecord>} users;
*
* }
* </code></pre>
*
* <p>修正したPOJOを使ってシートを書き込むときは、 XlsMapper#save メソッドを利用します。</p>
*
* <pre class="highlight"><code class="java">
* // 書き込むシート情報の作成
* UserSheet sheet = new UserSheet();
* sheet.createDate = new Date();
*
* {@literal List<UserRecord>} users = new {@literal ArrayList<>}();
*
* // 1レコード分の作成
* UserRecord record1 = new UserRecord();
* record1.no = 1;
* record1.className = "A";
* record1.name = "Ichiro";
* record1.gender = Gender.male;
* users.add(record1);
*
* UserRecord record2 = new UserRecord();
* // ... 省略
* users.add(record2);
*
* sheet.users = users;
*
* // シートの書き込み
* XlsMapper xlsMapper = new XlsMapper();
* xlsMapper.save(
* new FileInputStream("template.xls"), // テンプレートのExcelファイル
* new FileOutputStream("out.xls"), // 書き込むExcelファイル
* sheet // 作成したデータ
* );
* </code></pre>
*
* @version 2.0
* @author T.TSUCHIE
*
*/
public class XlsMapper {
private Configuration configuration;
private XlsLoader loader;
private XlsSaver saver;
/**
* デフォルトコンストラクタ
*/
public XlsMapper() {
this.configuration = new Configuration();
this.loader = new XlsLoader(getConfiguration());
this.saver = new XlsSaver(getConfiguration());
}
/**
* システム情報を取得します。
* @return 現在のシステム情報
*/
public Configuration getConfiguration() {
return configuration;
}
/**
* システム情報を設定します。
* @param configuration システム情報
*/
public void setConfiguration(Configuration configuration) {
this.configuration = configuration;
getLoader().setConfiguration(configuration);
getSaver().setConfiguration(configuration);
}
/**
* 読み込み用クラスを取得します。
* @return 読み込み用クラス
*/
public XlsLoader getLoader() {
return loader;
}
/**
* 保存用クラスを取得します。
* @return 保存用クラス。
*/
public XlsSaver getSaver() {
return saver;
}
/**
* Excelファイルの1シートを読み込み、任意のクラスにマッピングする。
*
* @param <P> シートをマッピングするクラスタイプ
* @param xlsIn 読み込みもとのExcelファイルのストリーム。
* @param clazz マッピング先のクラスタイプ。
* @return シートをマッピングしたオブジェクト。
* {@link Configuration#isIgnoreSheetNotFound()}の値がtrueで、シートが見つからない場合、nullを返します。
* @throws IllegalArgumentException {@literal xlsIn == null or clazz == null}
* @throws XlsMapperException Excelファイルのマッピングに失敗した場合
* @throws IOException ファイルの読み込みに失敗した場合
*
*/
public <P> P load(final InputStream xlsIn, final Class<P> clazz) throws XlsMapperException, IOException {
return loader.load(xlsIn, clazz);
}
/**
* Excelファイルの1シートを読み込み、任意のクラスにマッピングする。
*
* @param <P> シートをマッピングするクラスタイプ
* @param xlsIn 読み込みもとのExcelファイルのストリーム。
* @param clazz マッピング先のクラスタイプ。
* @return シートのマッピング結果。
* {@link Configuration#isIgnoreSheetNotFound()}の値がtrueで、シートが見つからない場合、nullを返します。
* @throws IllegalArgumentException {@literal xlsIn == null or clazz == null}
* @throws XlsMapperException Excelファイルのマッピングに失敗した場合
* @throws IOException ファイルの読み込みに失敗した場合
*/
public <P> SheetBindingErrors<P> loadDetail(final InputStream xlsIn, final Class<P> clazz) throws XlsMapperException, IOException {
return loader.loadDetail(xlsIn, clazz);
}
/**
* Excelファイルの複数シートを読み込み、任意のクラスにマップする。
* <p>{@link XlsSheet#regex()}により、複数のシートが同じ形式で、同じクラスにマッピングすする際に使用します。</p>
*
* @param xlsIn 読み込み元のExcelファイルのストリーム。
* @param clazz マッピング先のクラスタイプ。
* @return マッピングした複数のシート。
* {@link Configuration#isIgnoreSheetNotFound()}の値がtrueで、シートが見つからない場合、マッピング結果には含まれません。
* @throws IllegalArgumentException {@literal xlsIn == null or clazz == null}
* @throws XlsMapperException マッピングに失敗した場合
* @throws IOException ファイルの読み込みに失敗した場合
*/
public <P> P[] loadMultiple(final InputStream xlsIn, final Class<P> clazz) throws XlsMapperException, IOException {
return loader.loadMultiple(xlsIn, clazz);
}
/**
* XMLによるマッピングを指定し、Excelファイルの複数シートを読み込み、任意のクラスにマップする。
* <p>{@link XlsSheet#regex()}により、複数のシートが同じ形式で、同じクラスにマッピングすする際に使用します。</p>
*
* @param <P> シートをマッピングするクラスタイプ
* @param xlsIn 読み込み元のExcelファイルのストリーム。
* @param clazz マッピング先のクラスタイプ。
* @return 複数のシートのマッピング結果。
* {@link Configuration#isIgnoreSheetNotFound()}の値がtrueで、シートが見つからない場合、マッピング結果には含まれません。
* @throws IllegalArgumentException {@literal xlsIn == null or clazz == null}
* @throws XlsMapperException マッピングに失敗した場合
* @throws IOException ファイルの読み込みに失敗した場合
*/
public <P> MultipleSheetBindingErrors<P> loadMultipleDetail(final InputStream xlsIn, final Class<P> clazz)
throws XlsMapperException, IOException {
return loader.loadMultipleDetail(xlsIn, clazz);
}
/**
* Excelファイルの複数シートを読み込み、任意のクラスにマップする。
* <p>複数のシートの形式を一度に読み込む際に使用します。</p>
*
* @param xlsIn 読み込み元のExcelファイルのストリーム。
* @param classes マッピング先のクラスタイプの配列。
* @return マッピングした複数のシート。
* {@link Configuration#isIgnoreSheetNotFound()}の値がtrueで、シートが見つからない場合、マッピング結果には含まれません。
* @throws IllegalArgumentException {@literal xlsIn == null or classes == null}
* @throws IllegalArgumentException {@literal calsses.length == 0}
* @throws XlsMapperException マッピングに失敗した場合
* @throws IOException ファイルの読み込みに失敗した場合
*/
public Object[] loadMultiple(final InputStream xlsIn, final Class<?>[] classes) throws XlsMapperException, IOException {
return loader.loadMultiple(xlsIn, classes);
}
/**
* Excelファイルの複数シートを読み込み、任意のクラスにマップする。
* <p>複数のシートの形式を一度に読み込む際に使用します。</p>
*
* @param xlsIn 読み込み元のExcelファイルのストリーム。
* @param classes マッピング先のクラスタイプの配列。
* @return マッピングした複数のシートの結果。
* {@link Configuration#isIgnoreSheetNotFound()}の値がtrueで、シートが見つからない場合、マッピング結果には含まれません。
* @throws IllegalArgumentException {@literal xlsIn == null or classes == null}
* @throws IllegalArgumentException {@literal calsses.length == 0}
* @throws IOException ファイルの読み込みに失敗した場合
* @throws XlsMapperException マッピングに失敗した場合
*/
public MultipleSheetBindingErrors<Object> loadMultipleDetail(final InputStream xlsIn, final Class<?>[] classes)
throws XlsMapperException, IOException {
return loader.loadMultipleDetail(xlsIn, classes);
}
/**
* JavaのオブジェクトをExeclファイルに出力する。
* <p>出力するファイルは、引数で指定した雛形となるテンプレート用のExcelファイルをもとに出力する。</p>
*
* @param templateXlsIn 雛形となるExcelファイルの入力
* @param xlsOut 出力先のストリーム
* @param beanObj 書き込むBeanオブジェクト
* @throws IllegalArgumentException {@literal templateXlsIn == null or xlsOut == null or beanObj == null}
* @throws XlsMapperException マッピングに失敗した場合
* @throws IOException テンプレートのファイルの読み込みやファイルの出力に失敗した場合
*/
public void save(final InputStream templateXlsIn, final OutputStream xlsOut, final Object beanObj) throws XlsMapperException, IOException {
saver.save(templateXlsIn, xlsOut, beanObj);
}
/**
* JavaのオブジェクトをExeclファイルに出力する。
* <p>出力するファイルは、引数で指定した雛形となるテンプレート用のExcelファイルをもとに出力する。</p>
*
* @param <P> マッピング対象のクラスタイプ
* @param templateXlsIn 雛形となるExcelファイルの入力
* @param xlsOut 出力先のストリーム
* @param beanObjs 書き込むBeanオブジェクト
* @return マッピング結果。
* {@link Configuration#isIgnoreSheetNotFound()}の値がtrueで、シートが見つからない場合、nullを返します。
* @throws IllegalArgumentException {@literal templateXlsIn == null or xlsOut == null or beanObj == null}
* @throws XlsMapperException マッピングに失敗した場合
* @throws IOException テンプレートのファイルの読み込みやファイルの出力に失敗した場合
*/
public <P> SheetBindingErrors<P> saveDetail(final InputStream templateXlsIn, final OutputStream xlsOut, final P beanObjs) throws XlsMapperException, IOException {
return saver.saveDetail(templateXlsIn, xlsOut, beanObjs);
}
/**
* 複数のオブジェクトをそれぞれのシートへ保存する。
* @param templateXlsIn 雛形となるExcelファイルの入力
* @param xlsOut xlsOut 出力先のストリーム
* @param beanObj 書き込むオブジェクトの配列。
* @throws IllegalArgumentException {@literal templateXlsIn == null or xlsOut == null or beanObjs == null}
* @throws IllegalArgumentException {@literal }
* @throws XlsMapperException マッピングに失敗した場合
* @throws IOException テンプレートのファイルの読み込みやファイルの出力に失敗した場合
*/
public void saveMultiple(final InputStream templateXlsIn, final OutputStream xlsOut, final Object[] beanObj) throws XlsMapperException, IOException {
saver.saveMultiple(templateXlsIn, xlsOut, beanObj);
}
/**
* 複数のオブジェクトをそれぞれのシートへ保存する。
* @param templateXlsIn 雛形となるExcelファイルの入力
* @param xlsOut xlsOut 出力先のストリーム
* @param beanObjs 書き込むオブジェクトの配列。
* @return マッピング結果。
* {@link Configuration#isIgnoreSheetNotFound()}の値がtrueで、シートが見つからない場合、結果に含まれません。
* @throws IllegalArgumentException {@literal templateXlsIn == null or xlsOut == null or beanObjs == null}
* @throws IllegalArgumentException {@literal }
* @throws XlsMapperException マッピングに失敗した場合
* @throws IOException テンプレートのファイルの読み込みやファイルの出力に失敗した場合
*/
public MultipleSheetBindingErrors<Object> saveMultipleDetail(final InputStream templateXlsIn, final OutputStream xlsOut, final Object[] beanObjs) throws XlsMapperException, IOException {
return saver.saveMultipleDetail(templateXlsIn, xlsOut, beanObjs);
}
}