blanco.cg.transformer.delphi.BlancoCgClassDelphiSourceExpander Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of blanco-cg Show documentation
Show all versions of blanco-cg Show documentation
blancoCg is a simple code generator library. blancoCg supports Java/C#/JavaScript/VB.NET/PHP/Ruby/Python/Delphi/Swift/C++11.
/*
* blanco Framework
* Copyright (C) 2004-2017 IGA Tosiki
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*/
/*
* Copyright 2017 Toshiki Iga
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package blanco.cg.transformer.delphi;
import java.util.ArrayList;
import java.util.List;
import blanco.cg.valueobject.BlancoCgClass;
import blanco.cg.valueobject.BlancoCgEnum;
import blanco.cg.valueobject.BlancoCgField;
import blanco.cg.valueobject.BlancoCgLangDoc;
import blanco.cg.valueobject.BlancoCgMethod;
import blanco.cg.valueobject.BlancoCgSourceFile;
import blanco.cg.valueobject.BlancoCgType;
/**
* BlancoCgClassをソースコードへと展開します。
*
* このクラスはblancoCgのバリューオブジェクトからソースコードを自動生成するトランスフォーマーの個別の展開機能です。
*
* @author IGA Tosiki
*/
class BlancoCgClassDelphiSourceExpander {
/**
* ここでClassを展開します。
*
* @param cgClass
* 処理対象となるクラス。
* @param argSourceLines
* ソースコード。
*/
public void transformClass(final BlancoCgClass cgClass,
final BlancoCgSourceFile argSourceFile,
final List argSourceLines) {
// 最初にクラス情報をLangDocに展開。
if (cgClass.getLangDoc() == null) {
// LangDoc未指定の場合にはこちら側でインスタンスを生成。
cgClass.setLangDoc(new BlancoCgLangDoc());
}
if (cgClass.getLangDoc().getTitle() == null) {
cgClass.getLangDoc().setTitle(cgClass.getDescription());
}
// 次に LangDocをソースコード形式に展開。
new BlancoCgLangDocDelphiSourceExpander().transformLangDoc(cgClass
.getLangDoc(), argSourceLines);
// アノテーションを展開。
expandAnnotationList(cgClass, argSourceLines);
final StringBuffer buf = new StringBuffer();
// Delphiではclass自体に可視性を設定しません
// if (BlancoStringUtil.null2Blank(cgClass.getAccess()).length() > 0) {
// buf.append(cgClass.getAccess() + " ");
// }
// if (cgClass.getAbstract()) {
// buf.append("abstract ");
// }
// if (cgClass.getFinal()) {
// buf.append("final ");
// }
buf.append(cgClass.getName());
// 親クラスを展開。
expandExtendClassList(cgClass, argSourceFile, buf);
// 親インタフェースを展開。
expandImplementInterfaceList(cgClass, argSourceFile, buf);
// 行を確定して書き出しを実施。
argSourceLines.add(buf.toString());
// クラスのブロックの開始。
argSourceLines.add("");
// ここで列挙体を展開。
// expandEnumList(cgClass, argSourceFile, argSourceLines);
// ここでフィールドを展開。
expandFieldList(cgClass, argSourceFile, argSourceLines);
// ここでメソッド宣言を展開。
expandMethodDeclarationList(cgClass, argSourceFile, argSourceLines);
// クラスのブロックの終了。
argSourceLines.add("end;");
// implementation
argSourceLines.add("implementation");
// ここでメソッドを展開。
expandMethodList(cgClass, argSourceFile, argSourceLines);
// end.
argSourceLines.add("end.");
}
/**
* アノテーションを展開します。
*
* @param cgClass
* クラス。
* @param argSourceLines
* ソースコード。
*/
private void expandAnnotationList(final BlancoCgClass cgClass,
final List argSourceLines) {
for (int index = 0; index < cgClass.getAnnotationList().size(); index++) {
final String strAnnotation = cgClass.getAnnotationList().get(index);
// C#.NET言語のAnnotationは []で記述します。
argSourceLines.add("[" + strAnnotation + "]");
}
}
/**
* 親クラスを展開します。
*
* ※BlancoCgInterface展開の際に、このメソッドを共通処理として呼び出してはなりません。
* その共通化は、かえって理解を妨げると判断しています。
*
* @param cgClass
* クラスのバリューオブジェクト。
* @param argBuf
* 出力先文字列バッファ。
*/
private void expandExtendClassList(final BlancoCgClass cgClass,
final BlancoCgSourceFile argSourceFile, final StringBuffer argBuf) {
if (cgClass.getExtendClassList().size() == 0) {
argBuf.append(" = class(TObject)");
return;
}
for (int index = 0; index < cgClass.getExtendClassList().size(); index++) {
final BlancoCgType type = cgClass.getExtendClassList().get(index);
// import文に型を追加。
// argSourceFile.getImportList().add(type.getName());
if (index == 0) {
argBuf.append(" = class("
+ BlancoCgTypeDelphiSourceExpander.toTypeString(type)
+ ")");
} else {
// TODO C#.NETの継承が一度きりだったかどうか確認を実施すること。
// throw new
// IllegalArgumentException("C#.NET言語では継承は一回しか実施できません。");
// TODO 現時点では多重継承がOKであると想定します。
argBuf.append(", "
+ BlancoCgTypeDelphiSourceExpander.toTypeString(type));
}
}
}
/**
* 親インタフェースを展開します。
*
* @param cgClass
* 処理中のクラス。
* @param argBuf
* 出力先文字列バッファ。
*/
private void expandImplementInterfaceList(final BlancoCgClass cgClass,
final BlancoCgSourceFile argSourceFile, final StringBuffer argBuf) {
for (int index = 0; index < cgClass.getImplementInterfaceList().size(); index++) {
final BlancoCgType type = cgClass.getImplementInterfaceList().get(
index);
// import文に型を追加。
// argSourceFile.getImportList().add(type.getName());
if (index == 0 && cgClass.getExtendClassList().size() == 0) {
// 最初のインタフェースで、且つ継承が無い場合に : を出力します。
argBuf.append(" : ");
} else {
argBuf.append(", ");
}
argBuf.append(BlancoCgTypeDelphiSourceExpander.toTypeString(type));
}
}
/**
* クラスに含まれる各々の列挙体を展開します。
*
* @param cgClass
* 処理中のクラス。
* @param argSourceFile
* ソースファイル。
* @param argSourceLines
* ソースコード行リスト。
*/
private void expandEnumList(final BlancoCgClass cgClass,
final BlancoCgSourceFile argSourceFile,
final List argSourceLines) {
if (cgClass.getEnumList() == null) {
return;
}
for (BlancoCgEnum cgEnum : cgClass.getEnumList()) {
new BlancoCgEnumDelphiSourceExpander().transformEnum(cgEnum,
argSourceFile, argSourceLines);
}
}
/**
* クラスに含まれる各々のフィールドを展開します。
*
* TODO 定数宣言を優先して展開し、その後変数宣言を展開するなどの工夫が必要です。
* 現在は 登録順でソースコード展開します。
*
* @param cgClass
* 処理中のクラス。
* @param argSourceFile
* ソースファイル。
* @param argSourceLines
* ソースコード行リスト。
*/
private void expandFieldList(final BlancoCgClass cgClass,
final BlancoCgSourceFile argSourceFile,
final List argSourceLines) {
if (cgClass.getFieldList() == null) {
// フィールドのリストにnullが与えられました。
// かならずフィールドのリストにはListをセットしてください。
throw new IllegalArgumentException("フィールドのリストにnullが与えられました。");
}
List publishedList = new ArrayList();
List publicList = new ArrayList();
List privateList = new ArrayList();
for (int index = 0; index < cgClass.getFieldList().size(); index++) {
final BlancoCgField cgField = cgClass.getFieldList().get(index);
String access = cgField.getAccess();
if (isPublished(access)) {
publishedList.add(cgField);
} else if (isPublic(access)) {
publicList.add(cgField);
} else if (isPrivate(access)) {
privateList.add(cgField);
} else {
// サポートされない
}
}
// published フィールドの展開
if (publishedList.size() > 0) {
argSourceLines.add("published");
}
for (int index = 0; index < publishedList.size(); index++) {
final BlancoCgField cgField = publishedList.get(index);
// クラスのフィールドとして展開を行います。
new BlancoCgFieldDelphiSourceExpander().transformField(cgField,
argSourceFile, argSourceLines, false);
}
// public フィールドの展開
if (publicList.size() > 0) {
argSourceLines.add("public");
}
for (int index = 0; index < publicList.size(); index++) {
final BlancoCgField cgField = publicList.get(index);
// クラスのフィールドとして展開を行います。
new BlancoCgFieldDelphiSourceExpander().transformField(cgField,
argSourceFile, argSourceLines, false);
}
// private フィールドの展開
if (privateList.size() > 0) {
argSourceLines.add("private");
}
for (int index = 0; index < privateList.size(); index++) {
final BlancoCgField cgField = privateList.get(index);
// クラスのフィールドとして展開を行います。
new BlancoCgFieldDelphiSourceExpander().transformField(cgField,
argSourceFile, argSourceLines, false);
}
}
/**
* クラスに含まれる各々のメソッド宣言を展開します。
*
* @param cgClass
* 処理中のクラス。
* @param argSourceFile
* ソースファイル。
* @param argSourceLines
* ソースコード行リスト。
*/
private void expandMethodDeclarationList(final BlancoCgClass cgClass,
final BlancoCgSourceFile argSourceFile,
final List argSourceLines) {
if (cgClass.getMethodList() == null) {
throw new IllegalArgumentException("メソッドのリストにnullが与えられました。");
}
List publishedList = new ArrayList();
List publicList = new ArrayList();
List privateList = new ArrayList();
for (int index = 0; index < cgClass.getMethodList().size(); index++) {
final BlancoCgMethod cgMethod = cgClass.getMethodList().get(index);
String access = cgMethod.getAccess();
if (isPublished(access)) {
publishedList.add(cgMethod);
} else if (isPublic(access)) {
publicList.add(cgMethod);
} else if (isPrivate(access)) {
privateList.add(cgMethod);
} else {
// サポートされない
}
}
// published メソッドの展開
if (publishedList.size() > 0) {
// 改行を付与。
argSourceLines.add("");
argSourceLines.add("published");
}
for (int index = 0; index < publishedList.size(); index++) {
final BlancoCgMethod cgMethod = publishedList.get(index);
// クラスのフィールドとして展開を行います。
new BlancoCgMethodDelphiSourceExpander()
.transformMethodDeclaration(cgMethod, argSourceFile,
argSourceLines, false);
}
// public メソッドの展開
if (publicList.size() > 0) {
// 改行を付与。
argSourceLines.add("");
argSourceLines.add("public");
}
for (int index = 0; index < publicList.size(); index++) {
final BlancoCgMethod cgMethod = publicList.get(index);
// クラスのフィールドとして展開を行います。
new BlancoCgMethodDelphiSourceExpander()
.transformMethodDeclaration(cgMethod, argSourceFile,
argSourceLines, false);
}
// private メソッドの展開
if (privateList.size() > 0) {
// 改行を付与。
argSourceLines.add("");
argSourceLines.add("private");
}
for (int index = 0; index < privateList.size(); index++) {
final BlancoCgMethod cgMethod = privateList.get(index);
// クラスのフィールドとして展開を行います。
new BlancoCgMethodDelphiSourceExpander()
.transformMethodDeclaration(cgMethod, argSourceFile,
argSourceLines, false);
}
}
/**
* クラスに含まれる各々のメソッドを展開します。
*
* @param cgClass
* 処理中のクラス。
* @param argSourceFile
* ソースファイル。
* @param argSourceLines
* ソースコード行リスト。
*/
private void expandMethodList(final BlancoCgClass cgClass,
final BlancoCgSourceFile argSourceFile,
final List argSourceLines) {
if (cgClass.getMethodList() == null) {
throw new IllegalArgumentException("メソッドのリストにnullが与えられました。");
}
for (int index = 0; index < cgClass.getMethodList().size(); index++) {
final BlancoCgMethod cgMethod = cgClass.getMethodList().get(index);
// クラスのメソッドとして展開を行います。
new BlancoCgMethodDelphiSourceExpander().transformMethod(cgClass
.getName(), cgMethod, argSourceFile, argSourceLines, false);
}
}
private boolean isPrivate(String access) {
return "private".equals(access);
}
private boolean isPublic(String access) {
return "public".equals(access);
}
private boolean isPublished(String access) {
return "".equals(access) || "published".equals(access);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy