S-JIS[2018-11-25] 変更履歴

AsakusaFW DMDLパーサーを使う例

Asakusa FrameworkのDMDLパーサーを使う方法。

 

概要

Asakusa Frameworkのdmdlファイル(を解析した結果)を自分のJavaアプリケーションから使うには、DMDLのParserを呼び出せばよい。

DMDLのParser(jarファイル)は通常のAsakusaアプリケーションを開発する環境には入っていない。
Parserだけならbuild.gradleのdependenciesにasakusa-dmdl-coreを加えればいいが、実際の解析には他のライブラリーも必要になる。
(@directio.csvといった属性は他のライブラリー(SPI)で解析する為)
どのライブラリーが必要かいちいち調べるのは面倒なので、EclipseのAsakusaプロジェクトを作ったときに生成されるDMDLのライブラリー一覧が書かれている設定ファイルを読み込むのが楽。


build.gradleの例

dmdlファイルを読み込むJavaアプリケーションのbuild.gradleは、通常のAsakusaアプリケーション開発用のbuild.gradleを改造して使うのが楽だと思う。

build.gradle:

group 'com.example'

buildscript {
    repositories {
        maven { url 'http://asakusafw.s3.amazonaws.com/maven/releases' }
        maven { url 'http://asakusafw.s3.amazonaws.com/maven/snapshots' }
    }
    dependencies {
        classpath group: 'com.asakusafw.gradle', name: 'asakusa-distribution', version: '0.10.2'
    }
}

apply plugin: 'asakusafw-sdk'
apply plugin: 'asakusafw-organizer'
apply plugin: 'asakusafw-mapreduce'
apply plugin: 'asakusafw-spark'
apply plugin: 'eclipse'

// 以下を追加
dependencies {
    compile group: 'com.asakusafw', name: 'asakusa-dmdl-core', version: asakusafw.asakusafwVersion
}

dmdlファイルを読み込む例

package com.example.dmdl;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLClassLoader;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Properties;

import com.asakusafw.dmdl.model.AstAttribute;
import com.asakusafw.dmdl.model.AstAttributeElement;
import com.asakusafw.dmdl.model.AstDescription;
import com.asakusafw.dmdl.semantics.DmdlSemantics;
import com.asakusafw.dmdl.semantics.ModelDeclaration;
import com.asakusafw.dmdl.source.DmdlSourceRepository;
import com.asakusafw.dmdl.util.AnalyzeTask;
import com.asakusafw.dmdl.util.CommandLineUtils;
public class DmdlParserExample {

	public static void main(String... args) throws IOException {
		String projectDir = "D:/workspace/afw10.2";
		String dmdlDir = projectDir + "/src/main/dmdl";
		String prefsFile = projectDir + "/.settings/com.asakusafw.dmdl.prefs";

		List<File> dmdlFiles = Collections.singletonList(new File(dmdlDir));
		execute(dmdlFiles, new File(prefsFile));
	}
	public static void execute(List<File> dmdlFiles, File dmdlPrefsFile) throws IOException {
		DmdlSourceRepository repository = CommandLineUtils.buildRepository(dmdlFiles, StandardCharsets.UTF_8);
		ClassLoader loader = getDmdlClassLoader(dmdlPrefsFile);
		AnalyzeTask analyzeTask = new AnalyzeTask("example", loader);
		DmdlSemantics semantics = analyzeTask.process(repository);

		// System.out.println("====diagnostics====");
		// System.out.println(semantics.getDiagnostics());

		System.out.println("====dataModel====");
		Collection<ModelDeclaration> modelList = semantics.getDeclaredModels();
		for (ModelDeclaration model : modelList) {
			// System.out.println(model);
			AstDescription description = model.getDescription();
			if (description != null) {
				System.out.println(description.token);
			}
			System.out.println(model.getName().identifier);
			printAttribute(model.getAttributes());
			System.out.println(model.getDeclaredProperties());
			System.out.println("----");
		}
	}

dmdlファイルを解析(パース)するには、DmdlParserとDmdlAnalyzerというクラスを使用する。
が、ちょっとややこしいので、それらを呼び出しているAnalyzeTaskを使うのが楽。
解析結果はDmdlSemanticsで返ってくる。この中にデータモデル一覧が入っている。
ただし、これらは構文解析木(AST)のクラスなので、自分が欲しい形式へは自分で変換する必要がある。

	static ClassLoader getDmdlClassLoader(File dmdlPrefsFile) throws IOException {
		Properties properties = new Properties();
		try (InputStream is = Files.newInputStream(dmdlPrefsFile.toPath())) {
			properties.load(is);
		}

		List<URL> urlList = new ArrayList<>();
		for (int i = 0;; i++) {
			String key = "classpath." + i;
			String path = properties.getProperty(key);
			if (path == null) {
				break;
			}
			urlList.add(new File(path).toURI().toURL());
		}

		return URLClassLoader.newInstance(urlList.toArray(new URL[urlList.size()]));
	}

概要に書いたとおり、@directio.csv等の属性は別ライブラリーで解釈される。
このライブラリー(jarファイル)は「AsakusaアプリケーションのEclipseプロジェクト/.settings/com.asakusafw.dmdl.prefs」に書かれているので、それを読み込んでクラスローダーを作成している。

	static void printAttribute(List<AstAttribute> attributeList) {
		for (AstAttribute attribute : attributeList) {
			System.out.print("@" + attribute.name);
			System.out.println("(");
			for (AstAttributeElement element : attribute.elements) {
				System.out.println(element.name + " = " + element.value);
			}
			System.out.println(")");
		}
	}
}

AsakusaFW目次へ戻る / 技術メモへ戻る
メールの送信先:ひしだま