package com.gh.mygreen.xlsmapper.cellconvert; import static com.gh.mygreen.xlsmapper.TestUtils.*; import static org.hamcrest.Matchers.*; import static org.junit.Assert.*; import java.awt.Point; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.InputStream; import java.io.OutputStream; import java.net.URI; import java.net.URISyntaxException; import java.util.ArrayList; import java.util.List; import java.util.Map; import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.CreationHelper; import org.apache.poi.ss.usermodel.Hyperlink; import org.junit.BeforeClass; import org.junit.Test; import com.gh.mygreen.xlsmapper.IsEmptyBuilder; import com.gh.mygreen.xlsmapper.Utils; import com.gh.mygreen.xlsmapper.XlsMapper; import com.gh.mygreen.xlsmapper.annotation.OverRecordOperate; import com.gh.mygreen.xlsmapper.annotation.RecordTerminal; import com.gh.mygreen.xlsmapper.annotation.XlsColumn; import com.gh.mygreen.xlsmapper.annotation.XlsConverter; import com.gh.mygreen.xlsmapper.annotation.XlsFormula; import com.gh.mygreen.xlsmapper.annotation.XlsHint; import com.gh.mygreen.xlsmapper.annotation.XlsHorizontalRecords; import com.gh.mygreen.xlsmapper.annotation.XlsIsEmpty; import com.gh.mygreen.xlsmapper.annotation.XlsSheet; import com.gh.mygreen.xlsmapper.cellconvert.converter.URICellConverter; import com.gh.mygreen.xlsmapper.validation.SheetBindingErrors; /** * リンクの変換テスト。 * <p>下記のConverterのテスタ * <ol> * <li>{@link URICellConverter} * <li>{@link CellLink} * * @version 1.5 * @since 0.5 * @author T.TSUCHIE * */ public class LinkCellConverterTest { /** * テスト結果ファイルの出力ディレクトリ */ private static File OUT_DIR; @BeforeClass public static void setUpBeforeClass() throws Exception { OUT_DIR = createOutDir(); } /** * リンクの読み込みテスト */ @Test public void test_load_link() throws Exception { XlsMapper mapper = new XlsMapper(); mapper.getConig().setContinueTypeBindFailure(true); try(InputStream in = new FileInputStream("src/test/data/convert.xlsx")) { SheetBindingErrors errors = new SheetBindingErrors(LinkSheet.class); LinkSheet sheet = mapper.load(in, LinkSheet.class, errors); if(sheet.simpleRecords != null) { for(SimpleRecord record : sheet.simpleRecords) { assertRecord(record, errors); } } if(sheet.formattedRecords != null) { for(FormattedRecord record : sheet.formattedRecords) { assertRecord(record, errors); } } if(sheet.formulaRecords != null) { for(FormulaRecord record : sheet.formulaRecords) { assertRecord(record, errors); } } } } private void assertRecord(final SimpleRecord record, final SheetBindingErrors errors) throws URISyntaxException { if(record.no == 1) { // 空文字 assertThat(record.uri, is(nullValue())); assertThat(record.link, is(nullValue())); } else if(record.no == 2) { // URL(ラベルが同じ) assertThat(record.uri, is(new URI("http://www.google.co.jp/"))); assertThat(record.link, is(new CellLink("http://www.google.co.jp/", "http://www.google.co.jp/"))); } else if(record.no == 3) { // URL(ラベルが異なる) assertThat(record.uri, is(new URI("http://www.google.co.jp/"))); assertThat(record.link, is(new CellLink("http://www.google.co.jp/", "Googleサイト"))); } else if(record.no == 4) { // 文字列 assertThat(record.uri, is(new URI("http://www.google.co.jp/"))); assertThat(record.link, is(new CellLink(null, "http://www.google.co.jp/"))); } else if(record.no == 5) { // メールアドレス assertThat(record.uri, is(new URI("mailto:hoge@google.com"))); assertThat(record.link, is(new CellLink("mailto:hoge@google.com", "hoge@google.com"))); } else if(record.no == 6) { // ファイルパス assertThat(record.uri, is(new URI("convert.xlsx"))); assertThat(record.link, is(new CellLink("convert.xlsx", ".\\convert.xlsx"))); } else if(record.no == 7) { // セルへのリンク assertThat(record.uri, is(new URI("リンク型!A1"))); assertThat(record.link, is(new CellLink("リンク型!A1", "セルへのリンク"))); } else if(record.no == 8) { // 不正なリンク+ラベルに空白を含む assertThat(record.uri, is(new URI("http://invalid.uri"))); assertThat(record.link, is(new CellLink("http://invalid.uri", " 空白を含むリンク "))); } else if(record.no == 9) { // 空白の文字列 assertThat(cellFieldError(errors, cellAddress(record.positions.get("uri"))).isTypeBindFailure(), is(true)); assertThat(record.link, is(new CellLink(null, " http://www.google.co.jp/ "))); } else if(record.no == 10) { // URL(ラベルが空白) assertThat(record.uri, is(new URI("http://www.google.co.jp/"))); assertThat(record.link, is(new CellLink("http://www.google.co.jp/", " "))); } else if(record.no == 11) { // 空白の文字 assertThat(cellFieldError(errors, cellAddress(record.positions.get("uri"))).isTypeBindFailure(), is(true)); assertThat(record.link, is(new CellLink(null, " "))); } else { fail(String.format("not support test case. No=%d.", record.no)); } } private void assertRecord(final FormattedRecord record, final SheetBindingErrors errors) throws URISyntaxException { if(record.no == 1) { // 空文字 assertThat(record.uri, is(new URI("http://myhome.com/"))); assertThat(record.link, is(new CellLink("http://myhome.com/", "http://myhome.com/"))); } else if(record.no == 2) { // URL(ラベルが同じ) assertThat(record.uri, is(new URI("http://www.google.co.jp/"))); assertThat(record.link, is(new CellLink("http://www.google.co.jp/", "http://www.google.co.jp/"))); } else if(record.no == 3) { // URL(ラベルが異なる) assertThat(record.uri, is(new URI("http://www.google.co.jp/"))); assertThat(record.link, is(new CellLink("http://www.google.co.jp/", "Googleサイト"))); } else if(record.no == 4) { // 文字列 assertThat(record.uri, is(new URI("http://www.google.co.jp/"))); assertThat(record.link, is(new CellLink(null, "http://www.google.co.jp/"))); } else if(record.no == 5) { // メールアドレス assertThat(record.uri, is(new URI("mailto:hoge@google.com"))); assertThat(record.link, is(new CellLink("mailto:hoge@google.com", "hoge@google.com"))); } else if(record.no == 6) { // ファイルパス assertThat(record.uri, is(new URI("convert.xlsx"))); assertThat(record.link, is(new CellLink("convert.xlsx", ".\\convert.xlsx"))); } else if(record.no == 7) { // セルへのリンク assertThat(record.uri, is(new URI("リンク型!A1"))); assertThat(record.link, is(new CellLink("リンク型!A1", "セルへのリンク"))); } else if(record.no == 8) { // 不正なリンク+ラベルに空白を含む assertThat(record.uri, is(new URI("http://invalid.uri"))); assertThat(record.link, is(new CellLink("http://invalid.uri", "空白を含むリンク"))); } else if(record.no == 9) { // 空白の文字列 assertThat(record.uri, is(new URI("http://www.google.co.jp/"))); assertThat(record.link, is(new CellLink(null, "http://www.google.co.jp/"))); } else if(record.no == 10) { // URL(ラベルが空白) assertThat(record.uri, is(new URI("http://www.google.co.jp/"))); assertThat(record.link, is(new CellLink("http://www.google.co.jp/", ""))); } else if(record.no == 11) { // 空白の文字 assertThat(record.uri, is(nullValue())); assertThat(record.link, is(nullValue())); } else { fail(String.format("not support test case. No=%d.", record.no)); } } private void assertRecord(final FormulaRecord record, final SheetBindingErrors errors) throws URISyntaxException { if(record.no == 1) { // 空文字 assertThat(record.uri, is(nullValue())); assertThat(record.link, is(nullValue())); } else if(record.no == 2) { // URL(ラベルが同じ) assertThat(record.uri, is(new URI("http://www.google.co.jp/"))); assertThat(record.link, is(new CellLink("http://www.google.co.jp/", "リンク2"))); } else { fail(String.format("not support test case. No=%d.", record.no)); } } /** * リンク型の書き込みテスト */ @Test public void test_save_link() throws Exception { // テストデータの作成 final LinkSheet outSheet = new LinkSheet(); // アノテーションなしのデータ作成 outSheet.add(new SimpleRecord() .comment("空文字")); outSheet.add(new SimpleRecord() .uri(new URI("http://www.google.co.jp/")) .link(new CellLink("http://www.google.co.jp/", "http://www.google.co.jp/")) .comment("URL(ラベルが同じ)")); outSheet.add(new SimpleRecord() .uri(new URI("http://www.google.co.jp/")) .link(new CellLink("http://www.google.co.jp/", "Googleサイト")) .comment("URL(ラベルが異なる)")); outSheet.add(new SimpleRecord() .uri(new URI("hoge@google.com")) .link(new CellLink("hoge@google.com", "hoge@google.com")) .comment("URL(メールアドレス)")); outSheet.add(new SimpleRecord() .uri(new URI("convert.xlsx")) .link(new CellLink("convert.xlsx", ".\\convert.xlsx")) .comment("ファイルパス")); outSheet.add(new SimpleRecord() .uri(new URI("A1")) .link(new CellLink("A1", "セルへのリンク")) .comment("セルへのリンク")); outSheet.add(new SimpleRecord() .uri(new URI("http://www.google.co.jp/")) .link(new CellLink("http://www.google.co.jp/", " 空白を含むリンク ")) .comment("空白を含むリンク")); outSheet.add(new SimpleRecord() .uri(new URI("http://www.google.co.jp/")) .link(new CellLink("http://www.google.co.jp/", " ")) .comment("ラベルが空白")); // アノテーションありのデータ作成 outSheet.add(new FormattedRecord() .comment("空文字")); outSheet.add(new FormattedRecord() .uri(new URI("http://www.google.co.jp/")) .link(new CellLink("http://www.google.co.jp/", "http://www.google.co.jp/")) .comment("URL(ラベルが同じ)")); outSheet.add(new FormattedRecord() .uri(new URI("http://www.google.co.jp/")) .link(new CellLink("http://www.google.co.jp/", "Googleサイト")) .comment("URL(ラベルが異なる)")); outSheet.add(new FormattedRecord() .uri(new URI("hoge@google.com")) .link(new CellLink("hoge@google.com", "hoge@google.com")) .comment("URL(メールアドレス)")); outSheet.add(new FormattedRecord() .uri(new URI("convert.xlsx")) .link(new CellLink("convert.xlsx", ".\\convert.xlsx")) .comment("ファイルパス")); outSheet.add(new FormattedRecord() .uri(new URI("A1")) .link(new CellLink("A1", "セルへのリンク")) .comment("セルへのリンク")); outSheet.add(new FormattedRecord() .uri(new URI("http://www.google.co.jp/")) .link(new CellLink("http://www.google.co.jp/", " 空白を含むリンク ")) .comment("空白を含むリンク")); outSheet.add(new FormattedRecord() .uri(new URI("http://www.google.co.jp/")) .link(new CellLink("http://www.google.co.jp/", " ")) .comment("ラベルが空白")); // 数式のデータ outSheet.add(new FormulaRecord().comment("空文字")); outSheet.add(new FormulaRecord().comment("http://www.google.co.jp/")); // ファイルへの書き込み XlsMapper mapper = new XlsMapper(); mapper.getConig().setContinueTypeBindFailure(true); File outFile = new File(OUT_DIR, "convert_link.xlsx"); try(InputStream template = new FileInputStream("src/test/data/convert_template.xlsx"); OutputStream out = new FileOutputStream(outFile)) { mapper.save(template, out, outSheet); } // 書き込んだファイルを読み込み値の検証を行う。 try(InputStream in = new FileInputStream(outFile)) { SheetBindingErrors errors = new SheetBindingErrors(LinkSheet.class); LinkSheet sheet = mapper.load(in, LinkSheet.class, errors); if(sheet.simpleRecords != null) { assertThat(sheet.simpleRecords, hasSize(outSheet.simpleRecords.size())); for(int i=0; i < sheet.simpleRecords.size(); i++) { assertRecord(sheet.simpleRecords.get(i), outSheet.simpleRecords.get(i), errors); } } if(sheet.formattedRecords != null) { assertThat(sheet.formattedRecords, hasSize(outSheet.formattedRecords.size())); for(int i=0; i < sheet.formattedRecords.size(); i++) { assertRecord(sheet.formattedRecords.get(i), outSheet.formattedRecords.get(i), errors); } } if(sheet.formulaRecords != null) { assertThat(sheet.formulaRecords, hasSize(outSheet.formulaRecords.size())); for(int i=0; i < sheet.formulaRecords.size(); i++) { assertRecord(sheet.formulaRecords.get(i), outSheet.formulaRecords.get(i), errors); } } } } /** * 書き込んだレコードを検証するための * @param inRecord * @param outRecord * @param errors */ private void assertRecord(final SimpleRecord inRecord, final SimpleRecord outRecord, final SheetBindingErrors errors) { System.out.printf("%s - assertRecord::%s no=%d, comment=%s\n", this.getClass().getSimpleName(), inRecord.getClass().getSimpleName(), inRecord.no, inRecord.comment); assertThat(inRecord.no, is(outRecord.no)); assertThat(inRecord.uri, is(outRecord.uri)); assertThat(inRecord.link, is(outRecord.link)); assertThat(inRecord.comment, is(outRecord.comment)); } /** * 書き込んだレコードを検証するための * @param inRecord * @param outRecord * @param errors * @throws URISyntaxException */ private void assertRecord(final FormattedRecord inRecord, final FormattedRecord outRecord, final SheetBindingErrors errors) throws URISyntaxException { System.out.printf("%s - assertRecord::%s no=%d, comment=%s\n", this.getClass().getSimpleName(), inRecord.getClass().getSimpleName(), inRecord.no, inRecord.comment); if(inRecord.no == 1) { assertThat(inRecord.no, is(outRecord.no)); assertThat(inRecord.uri, is(new URI("http://myhome.com/"))); assertThat(inRecord.link, is(new CellLink("http://myhome.com/", "http://myhome.com/"))); assertThat(inRecord.comment, is(outRecord.comment)); } else if(inRecord.no == 7) { assertThat(inRecord.no, is(outRecord.no)); assertThat(inRecord.uri, is(new URI("http://www.google.co.jp/"))); assertThat(inRecord.link, is(new CellLink("http://www.google.co.jp/", "空白を含むリンク"))); assertThat(inRecord.comment, is(outRecord.comment)); } else if(inRecord.no == 8) { assertThat(inRecord.no, is(outRecord.no)); assertThat(inRecord.uri, is(new URI("http://www.google.co.jp/"))); assertThat(inRecord.link, is(new CellLink("http://www.google.co.jp/", ""))); assertThat(inRecord.comment, is(outRecord.comment)); } else { assertThat(inRecord.no, is(outRecord.no)); assertThat(inRecord.uri, is(outRecord.uri)); assertThat(inRecord.link, is(outRecord.link)); assertThat(inRecord.comment, is(outRecord.comment)); } } /** * 書き込んだレコードを検証するための * @param inRecord * @param outRecord * @param errors * @throws URISyntaxException */ private void assertRecord(final FormulaRecord inRecord, final FormulaRecord outRecord, final SheetBindingErrors errors) throws URISyntaxException { System.out.printf("%s - assertRecord::%s no=%d, comment=%s\n", this.getClass().getSimpleName(), inRecord.getClass().getSimpleName(), inRecord.no, inRecord.comment); if(inRecord.no == 1) { assertThat(inRecord.no, is(outRecord.no)); assertThat(inRecord.uri, is(nullValue())); assertThat(inRecord.link, is(nullValue())); assertThat(inRecord.comment, is(outRecord.comment)); } else if(inRecord.no == 2) { assertThat(inRecord.no, is(outRecord.no)); assertThat(inRecord.uri, is(new URI("http://www.google.co.jp/"))); assertThat(inRecord.link, is(new CellLink("http://www.google.co.jp/", "リンク2"))); assertThat(inRecord.comment, is(outRecord.comment)); } else { fail(String.format("not support test case. No=%d.", inRecord.no)); } } @XlsSheet(name="リンク型") private static class LinkSheet { @XlsHint(order=1) @XlsHorizontalRecords(tableLabel="リンク型(アノテーションなし)", terminal=RecordTerminal.Border, ignoreEmptyRecord=true, overRecord=OverRecordOperate.Insert) private List<SimpleRecord> simpleRecords; @XlsHint(order=2) @XlsHorizontalRecords(tableLabel="リンク型(初期値、書式)", terminal=RecordTerminal.Border, ignoreEmptyRecord=true, overRecord=OverRecordOperate.Insert) private List<FormattedRecord> formattedRecords; @XlsHint(order=3) @XlsHorizontalRecords(tableLabel="リンク型(数式)", terminal=RecordTerminal.Border, ignoreEmptyRecord=true, overRecord=OverRecordOperate.Insert) private List<FormulaRecord> formulaRecords; /** * レコードを追加する。noを自動的に付与する。 * @param record * @return */ public LinkSheet add(SimpleRecord record) { if(simpleRecords == null) { this.simpleRecords = new ArrayList<>(); } this.simpleRecords.add(record); record.no(simpleRecords.size()); return this; } /** * レコードを追加する。noを自動的に付与する。 * @param record * @return */ public LinkSheet add(FormattedRecord record) { if(formattedRecords == null) { this.formattedRecords = new ArrayList<>(); } this.formattedRecords.add(record); record.no(formattedRecords.size()); return this; } /** * レコードを追加する。noを自動的に付与する。 * @param record * @return */ public LinkSheet add(FormulaRecord record) { if(formulaRecords == null) { this.formulaRecords = new ArrayList<>(); } this.formulaRecords.add(record); record.no(formulaRecords.size()); return this; } } /** * リンク型 - アノテーションなし * */ private static class SimpleRecord { private Map<String, Point> positions; private Map<String, String> labels; @XlsColumn(columnName="No.") private int no; @XlsColumn(columnName="URI") private URI uri; @XlsColumn(columnName="CellLink") private CellLink link; @XlsColumn(columnName="備考") private String comment; @XlsIsEmpty public boolean isEmpty() { return IsEmptyBuilder.reflectionIsEmpty(this, "positions", "labels", "no"); } public SimpleRecord no(int no) { this.no = no; return this; } public SimpleRecord uri(URI uri) { this.uri = uri; return this; } public SimpleRecord link(CellLink link) { this.link = link; return this; } public SimpleRecord comment(String comment) { this.comment = comment; return this; } } /** * リンク型 - 初期値など * */ private static class FormattedRecord { private Map<String, Point> positions; private Map<String, String> labels; @XlsColumn(columnName="No.") private int no; @XlsConverter(trim=true, defaultValue="http://myhome.com/") @XlsColumn(columnName="URI") private URI uri; @XlsConverter(trim=true, defaultValue="http://myhome.com/") @XlsColumn(columnName="CellLink") private CellLink link; @XlsColumn(columnName="備考") private String comment; @XlsIsEmpty public boolean isEmpty() { return IsEmptyBuilder.reflectionIsEmpty(this, "positions", "labels", "no"); } public FormattedRecord no(int no) { this.no = no; return this; } public FormattedRecord uri(URI uri) { this.uri = uri; return this; } public FormattedRecord link(CellLink link) { this.link = link; return this; } public FormattedRecord comment(String comment) { this.comment = comment; return this; } } /** * リンク型 - 数式な * */ private static class FormulaRecord { private Map<String, Point> positions; private Map<String, String> labels; @XlsColumn(columnName="No.") private int no; @XlsColumn(columnName="URI") @XlsFormula(methodName="getFormula1") private URI uri; @XlsColumn(columnName="CellLink") @XlsFormula(methodName="getFormula2") private CellLink link; @XlsColumn(columnName="備考") private String comment; @XlsIsEmpty public boolean isEmpty() { return IsEmptyBuilder.reflectionIsEmpty(this, "positions", "labels", "no"); } public String getFormula1(Point point) { if(Utils.equals(comment, "空文字")) { return null; } final int rowNumber = point.y + 1; return String.format("HYPERLINK(D%d)", rowNumber); } public String getFormula2(Point point, Cell cell) { if(Utils.equals(comment, "空文字")) { return null; } // ダミーでリンクも設定する final CreationHelper helper = cell.getSheet().getWorkbook().getCreationHelper(); final Hyperlink link = helper.createHyperlink(Hyperlink.LINK_URL); link.setAddress(comment); cell.setHyperlink(link); final int rowNumber = point.y + 1; return String.format("HYPERLINK(D%s,\"リンク\"&A%s)", rowNumber, rowNumber); } public FormulaRecord no(int no) { this.no = no; return this; } public FormulaRecord uri(URI uri) { this.uri = uri; return this; } public FormulaRecord link(CellLink link) { this.link = link; return this; } public FormulaRecord comment(String comment) { this.comment = comment; return this; } } }