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(")");
}
}
}