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のライブラリー一覧が書かれている設定ファイルを読み込むのが楽。
dmdlファイルを読み込むJavaアプリケーションのbuild.gradleは、通常のAsakusaアプリケーション開発用の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
}
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(")"); } } }