DataSpiderとブロックチェーン その9
前回は、NFT連携するためのDataSpiderによりシナリオについて紹介しました。
今回からNFT連携に必要となるアダプタの実装について紹介したいと思います。
やること
シナリオの❷ (※前回の記事で紹介しましたシナリオは以下の図を参照ください) で必要となるPDF生成の実装していきます。
PDFを生成するアダプタを作成したいと思います。
開発環境
前回から同様のWindows10上で行います。
DataSpiderもWindows版(体験版を使用)を用意ください。
ライブラリの準備
今回は、あたらにPDF生成のためのJavaライブラリをインストールします。
iTextのライブラリを取得します。
Java1.8でコンパイルする場合は、こちらのiText7 Githubから入手ください。
執筆時点では、iText Ver7.2.4を使用します。
iText7のビルド
git clone https://github.com/itext/itext7.git
cd itext7
git checkout 7.2.4
mvn clean install -D maven.test.skip=true
ビルドツール
Apache Maven 3.8.6
Maven home: C:\apache-maven-3.8.6-bin\apache-maven-3.8.6
Java version: 1.8.0_202, vendor: Oracle Corporation, runtime: C:\java\8\jre
Default locale: ja_JP, platform encoding: MS932
OS name: "windows 10", version: "10.0", arch: "amd64", family: "windows"
iText ライブラリ群
itext7-barcodes-7.2.4.jar
itext7-commons-7.2.4.jar
itext7-font-asian-7.2.4.jar
itext7-forms-7.2.4.jar
itext7-hyph-7.2.4.jar
itext7-io-7.2.4.jar
itext7-kernel-7.2.4.jar
itext7-layout-7.2.4.jar
itext7-pdfa-7.2.4.jar
itext7-pdftest-7.2.4.jar
itext7-sign-7.2.4.jar
itext7-styled-xml-parser-7.2.4.jar
itext7-svg-7.2.4.jar
iTextとは
PDFデータを生成するためのライブラリです。
フリー版(AGPLライセンス)と商用版が提供されています。
ライブラリは、Java言語と.NETの2種類があります。今回の検証では、Java言語用のライブラリを使用します。
公式ホームページ:https://itextpdf.com/products/itext-7
ナレッジサイトから色々な実装例を探すことができます。
ナレッジサイト:https://kb.itextpdf.com/home
アダプタの実装
PDFアダプタの利用イメージ
PDFアダプタの処理概要:
複数件ある受取者名簿の内容を読み込み1行1ファイルずつPDFファイルを生成します。
- プロパティ画面で、PDFに埋め込むロゴ画像、PDFファイルの出力先パス、PDFファイル生成時の接頭文字の設定欄を設けます。
- PDFに埋め込む文字列を受け取ります。
- 受け取った文字列と指定されたロゴ画像をPDFに埋め込みます。
- 指定されたパスにPDFファイルを出力します。
- 出力したファイル名をアドレスIDと共に後続のアダプタ向けの出力項目に格納します。
PDF出力部分のソースコード
ソースの構成
PDF出力処理をPutTronGeneratePdfOperation.javaに実装します。
iTextのライブラリを参照ライブラリの外部jarとして追加します。
PutTronGeneratePdfOperation.java
@Override
public Map execute(Map inputData) throws Exception {
Map res = new HashMap();
FileManager fm = (FileManager) getContext().getProxy(FileManager.class);
String imagePath = getImagePath();
String pdfOutputPath = getPdfOutputPath();
String pdfPrefix = getPdfPrefix();
LocalDateTime now = LocalDateTime.now();
DateTimeFormatter dateFormat = DateTimeFormatter.ofPattern("yyyy/MM/dd");
String payoutDate = now.format(dateFormat);
Object data = inputData.get(KEY_INPUT);
LoggingContext log = getContext().log();
// 出力側TableDataBuilderを生成する。
TableDataBuilder builder = DataBuilderFactory.newTableDataBuilder(getColumnOutputTypes(), isLargeData());
log.info(builder.toString());
try (TableRowIterator rowIterator = DataParserFactory.newTableRowIterator(data)) {
// 出力側項目の出力開始を宣言する
builder.startConstruction();
// 入力側レコードの繰り返し処理
while (rowIterator.hasNext()) {
Row record = rowIterator.next();
builder.startRow(); // 出力側行単位のデータを格納するバッファ
/*
* 入力側データ読み込み
*/
Column userIdColumn = record.getColumn(0);
String userId = getColumnValue(userIdColumn);
Column nameColumn = record.getColumn(1);
String name = getColumnValue(nameColumn);
Column addressColumn = record.getColumn(2);
String publicAddress = getColumnValue(addressColumn);
String dest = pdfOutputPath + "/" + pdfPrefix + publicAddress + ".pdf";
/*
* PDF出力
* 必要に応じてPDFテンプレートを読み込んでPDFを生成するロジックにする
*/
int counter = 1;
// 日本語対応のフォントを指定
PdfFont fontDetail = PdfFontFactory.createFont("HeiseiKakuGo-W5", "UniJIS-UCS2-H");
PdfWriter writer = new PdfWriter(fm.getOutputStream(dest));
PdfDocument pdf = new PdfDocument(writer);
pdf.setDefaultPageSize(PageSize.A6.rotate());
Document doc = new Document(pdf);
// SVGファイルのみ対応
Image myLogo = SvgConverter.convertToImage(fm.getInputStream(imagePath), pdf);
Paragraph p = new Paragraph("")
.add(myLogo);
p.setTextAlignment(TextAlignment.CENTER);
p.setVerticalAlignment(VerticalAlignment.TOP);
doc.add(p);
float[] columnWidths = {1, 4, 8};
Table table = new Table(UnitValue.createPercentArray(columnWidths));
Cell cell = new Cell(1, 3)
.add(new Paragraph("CERTIFICATE OF COMPLETION"))
.setWidth(1000)
.setFont(fontDetail)
.setFontSize(13)
.setFontColor(ColorConstants.WHITE)
.setBackgroundColor(ColorConstants.BLACK)
.setTextAlignment(TextAlignment.CENTER);
table.addHeaderCell(cell);
// 証明書の内容を1行ずつ生成する
table.addCell(new Cell().setTextAlignment(TextAlignment.CENTER).add(new Paragraph(String.valueOf(counter++))));
table.addCell(new Cell().setTextAlignment(TextAlignment.LEFT).add(new Paragraph("発行年月日").setFont(fontDetail).setFontSize(10)));
table.addCell(new Cell().setTextAlignment(TextAlignment.LEFT).add(new Paragraph(payoutDate).setFontSize(10)));
table.addCell(new Cell().setTextAlignment(TextAlignment.CENTER).add(new Paragraph(String.valueOf(counter++))));
table.addCell(new Cell().setTextAlignment(TextAlignment.LEFT).add(new Paragraph("受講者").setFont(fontDetail).setFontSize(10)));
table.addCell(new Cell().setTextAlignment(TextAlignment.LEFT).add(new Paragraph(name).setFont(fontDetail).setFontSize(10)));
table.addCell(new Cell().setTextAlignment(TextAlignment.CENTER).add(new Paragraph(String.valueOf(counter++))));
table.addCell(new Cell().setTextAlignment(TextAlignment.LEFT).add(new Paragraph("TRONアドレス").setFont(fontDetail).setFontSize(10)));
table.addCell(new Cell().setTextAlignment(TextAlignment.LEFT).add(new Paragraph(publicAddress).setFontSize(10)));
doc.add(table);
doc.add(new Paragraph("上記受講者は、" + payoutDate + "をもって受講修了したことを証明します").setFont(fontDetail).setFontSize(10));
doc.close();
/*
* 出力側項目格納
*/
// UserID
builder.column(userId);
log.debug("UserID = " + userId);
// senderAddress
builder.column(publicAddress);
log.debug("publicAddress = " + publicAddress);
// fileName
builder.column(pdfPrefix + publicAddress + ".pdf");
log.debug("fileName = " + pdfPrefix + publicAddress + ".pdf");
// 出力時間
builder.column(payoutDate);
builder.endRow();
}
builder.endConstruction();
Object result = builder.getResult();
res.put(KEY_OUTPUT, result);
}
return res;
}
PDF生成アダプタの設定項目
PDF生成アダプタのプロパティ画面
TronGeneratePdfOperationFactory.java
画面のプロパティ情報を実装します。
public abstract class TronGeneratePdfOperationFactory implements OperationFactory {
@Override
public OperationConfigurator createOperationConfigurator(
OperationConfiguration conf,
OperationContext context) throws Exception {
OperationConfigurator configurator = new OperationConfigurator(conf, context);
configurator.addGroup(new ParameterGroup(KEY_MUST_GROUP, MultiLangMessage.getString("group.type.label")));
configurator.addSimpleParameter(KEY_MUST_GROUP, createImagePathParameter());
configurator.addSimpleParameter(KEY_MUST_GROUP, createPdfOutputPathParameter());
configurator.addSimpleParameter(KEY_MUST_GROUP, createPdfPrefixParameter());
return configurator;
}
private SimpleParameter createImagePathParameter() {
Fillin constraint = new Fillin();
constraint.setLabel("PDFロゴパスファイル名");
constraint.setRequired(false);
constraint.setShortcut("L");
constraint.setLength(1024);
constraint.setDescription("1024 文字以内で設定してください");
SimpleParameter param = new SimpleParameter(KEY_IMAGE_PATH, constraint);
return param;
}
private SimpleParameter createPdfOutputPathParameter() {
Fillin constraint = new Fillin();
constraint.setLabel("PDF出力パス");
constraint.setRequired(false);
constraint.setShortcut("S");
constraint.setLength(1024);
constraint.setDescription("1024 文字以内で設定してください");
SimpleParameter param = new SimpleParameter(KEY_PDF_OUTPUT_PATH, constraint);
return param;
}
private SimpleParameter createPdfPrefixParameter() {
Fillin constraint = new Fillin();
constraint.setLabel("PDFファイルプレフィックス");
constraint.setRequired(false);
constraint.setShortcut("P");
constraint.setLength(1024);
constraint.setDescription("1024 文字以内で設定してください");
SimpleParameter param = new SimpleParameter(KEY_PDF_PREFIX, constraint);
return param;
}
String createInputSchema(OperationConfiguration conf) {
TableSchemaGenerator generator = new TableSchemaGenerator();
// 入力側の項目名称(固定)
String address_id = KEY_INPUT_COLNAME_ADDRESS_ID;
// 入力側の項目タイプ(固定)
String address_id_type = TYPE_STRING;
generator.addColumn(address_id, TableDataTypeUtil.parseType(address_id_type));
// 入力側の項目名称(固定)
String name = KEY_INPUT_COLNAME_NAME;
// 入力側の項目タイプ(固定)
String name_type = TYPE_STRING;
generator.addColumn(name, TableDataTypeUtil.parseType(name_type));
// 入力側の項目名称(固定)
String address = KEY_INPUT_COLNAME_ADDRESS;
// 入力側の項目タイプ(固定)
String address_type = TYPE_STRING;
generator.addColumn(address, TableDataTypeUtil.parseType(address_type));
// 文字列として XMLSchema を返します。
return generator.generateXMLSchema();
}
String createOutputSchema(OperationConfiguration conf) {
TableSchemaGenerator generator = new TableSchemaGenerator();
// 出力側の項目名称(固定)入力側のアドレスIDを格納
String name = KEY_OUTPUT_COLNAME_ADDRESS_ID;
// 出力側の項目タイプ(固定)
String type = TYPE_STRING;
generator.addColumn(name, TableDataTypeUtil.parseType(type));
// 出力側の項目名称(固定) 入力側のアドレスを格納
name = KEY_OUTPUT_COLNAME_ADDRESS;
// 出力側の項目タイプ(固定)
type = TYPE_STRING;
generator.addColumn(name, TableDataTypeUtil.parseType(type));
// 出力側の項目名称(固定) PDF出力パスファイル名を格納
name = KEY_OUTPUT_COLNAME_PDF_OUTPUT_PATH;
// 出力側の項目タイプ(固定)
type = TYPE_STRING;
generator.addColumn(name, TableDataTypeUtil.parseType(type));
// 出力側の項目名称(固定) PDF発行日を格納
name = KEY_OUTPUT_COLNAME_PDF_PAYOUT_DATE;
// 出力側の項目タイプ(固定)
type = TYPE_STRING;
generator.addColumn(name, TableDataTypeUtil.parseType(type));
// 文字列として XMLSchema を返します。
return generator.generateXMLSchema();
}
}
その他、画面から項目を取得するメソッドやアダプタアイコンを作成します。
詳細は、コンポーネントSDK 4.2 開発ガイドを参照ください。
- 画面項目の実装:5.2. MessageXML Adapter の作成
- アイコンの生成:18. オペレーションとグローバルリソースのアイコンファイルについて
DataSpiderスクリプトの作成
PDF出力アイコンが今回実装したアダプタです。
その前後のアイコンのマッピング状態を以下に記します。
全体像
PDF出力マッピング(PDF出力アイコンの入力側マッピング)
出力結果マッピング(PDF出力アイコンの出力側マッピング)
入出力ファイルと出力結果
証明書PDFファイル
PDFアダプタの実装と動作結果は以上です。
次回は
IPFS/NFT部分の実装を行います。