第057回_一般実体テーブル作成処理の実装1
»
5回にわたってW3Cの勧告を読み、仕様を整理しました。
仕様の整理に従って、
1.実体宣言から一般実体テーブルを作成する処理
2.実体宣言からパラメータ実体テーブルを作成する処理
3.内容(Content)内の参照の展開処理
を実装していきます。
まずは、一般実体から見ていきます。
実体宣言から一般実体テーブルの作成処理のクラス群
関連するクラスは次のようにします。クラス名 | 説明 |
GeneralEntityData | 一般実体データの抽象クラス |
AbstractInternalParsedEntityData | 内部・解析対象 ・一般実体データの抽象クラス |
InternalParsedEntityData | 内部・解析対象 ・一般実体 を表すデータクラス |
PredefinedEntityData | 内部・解析対象 ・一般実体の内定義済み実体 を表すデータクラス |
ExternalParsedEntityData | 外部・解析対象 ・一般実体 を表すデータクラス |
ExternalUnparsedEntityData | 外部・解析対象外・一般実体 を表すデータクラス |
GeTable | 一般実体テーブル(Mapをラッパーするクラス) |
MakingGeTableVisitor | 一般実体テーブルを作成するVisitor |
実装
■GeneralEntityDataの実装
GeneralEntityDataクラスは一般実体を表す抽象クラスです。
各フィールドの解説をします。
m_name : 一般実体名の値
m_inParametorDeclaration : DeclSep内の宣言を表す。trueはDeclSep内の宣言
m_inExtSubsetDeclaration : 外部サブセットの宣言を表す。trueは外部サブセット内の宣言
基底クラスではnullを返しておきます。
■AbstractInternalParsedEntityDataの実装
AbstractInternalParsedEntityDataは内部・解析対象・一般実体を表す抽象データクラスです。
抽象クラスを用意する理由は、定義済みのモノと定義済みでないモノの2種類があるからです。
■InternalParsedEntityDataの実装
InternalParsedEntityDataは内部・解析対象・一般実体を表すデータクラスです。
■PredefinedEntityDataの実装
PredefinedEntityDataは内部・解析対象・一般実体の内、定義済み実体 を表す抽象データクラスです。
定義済み実体は、次の機能を持ちます。
フィールド
m_baseList : 置換テキストとして指定できる文字列の候補リスト
m_nomalDeclared: 個別に定義した場合の内部・解析対象・一般実体のデータ(2つ目以降はマージするので1つだけ持つ)
メソッド
setList: 候補リストを設定する
marge : 登録済みデータが定義済み実体のマージ処理(一般実体のマージ処理をせずに定義済み実体はこちらを実行する)
1.内部・解析対象・一般実体データが未だ無い場合
1-1.登録側のデータが内部・解析対象・一般実体でない場合
1-1-1.エラーとする
1-2.登録側のデータが内部・解析対象・一般実体の場合
1-2-1.内部・解析対象・一般実体データとして保存する
1-2-2.候補リストの文字列の場合
1-2-2-1.置換文字列に設定する
1-2-3.候補リストの文字列でない場合
1-2-3-1.エラーとする
2.内部・解析対象・一般実体データが既に有る場合
2-1.内部・解析対象・一般実体データにマージする(定義済み実体でないマージ処理へ)
■ExternalParsedEntityDataの実装
ExternalParsedEntityDataは外部・解析対象・一般実体 を表すデータクラスです。
■ExternalUnparsedEntityDataの実装
ExternalUnparsedEntityDataは外部・解析対象外・一般実体を表すデータクラスです。
ただし、記法宣言との関連部分はまだ検討していないため、作成しません。
長くなったのでMakingGeTableVisitorの説明は次回にします。
GeneralEntityDataクラスは一般実体を表す抽象クラスです。
public abstract class GeneralEntityData
{
private String m_name;
//パラメータ実体の中で宣言された実体宣言かどうかのフラグ
//(整形式のチェックのために設定する)
private boolean m_inParametorDeclaration;
//外部サブセットの中で宣言された実体宣言かどうかのフラグ
//(整形式のチェックのために設定する)
private boolean m_inExtSubsetDeclaration;
public GeneralEntityData()
{
m_name="";
m_inParametorDeclaration = false;
m_inExtSubsetDeclaration = false;
}
public void setName(String name)
{
m_name = name;
}
public String getName()
{
return m_name;
}
public void setParametorDeclaration(boolean b)
{
m_inParametorDeclaration = b;
}
public void setExtSubsetDeclaration(boolean b)
{
m_inExtSubsetDeclaration = b;
}
//外部マークアップ宣言かどうかを判定する
public boolean isExternalMarkupDeclaration()
{
//DeclSep内で宣言した実体宣言の場合
//または、
//外部サブセット内で宣言した実体宣言の場合
//外部マークアップ宣言として、trueを返す
return (m_inParametorDeclaration || m_inExtSubsetDeclaration);
}
//同名のデータで2つ目以降のデータがきた場合に呼び出す
public void marge(GeneralEntityData ged)
{
//TODO オプションが有効なら警告を出しても良い
}
//定義済み実体に対して同名の一般実体を取得するためのメソッド
public InternalParsedEntityData getInstanceIfInternalParsedEntity()
{
return null;
}
}
m_name : 一般実体名の値
m_inParametorDeclaration : DeclSep内の宣言を表す。trueはDeclSep内の宣言
m_inExtSubsetDeclaration : 外部サブセットの宣言を表す。trueは外部サブセット内の宣言
既に説明した整形式性制約をチェックする場合に、外部マークアップ宣言かを判定
する必要があるため、DeclSepと外部サブセットの中で宣言したものかの情報を持ちます。
margeメソッドは、同名のkeyに対して重複して宣言した場合の処理になります。
オプションによって警告を出す処理が必要ですが、例外やエラーに対するクラスがないので何もしていません。
基底クラスではnullを返しておきます。
■AbstractInternalParsedEntityDataの実装
AbstractInternalParsedEntityDataは内部・解析対象・一般実体を表す抽象データクラスです。
抽象クラスを用意する理由は、定義済みのモノと定義済みでないモノの2種類があるからです。
public abstract class AbstractInternalParsedEntityData
extends GeneralEntityData
{
//置換テキスト
protected String m_replacementText;
public AbstractInternalParsedEntityData()
{
m_replacementText = "";
}
public String toString()
{
return m_replacementText;
}
@Override
public boolean canReferenceAtEntityValue(){return true;}
}
InternalParsedEntityDataは内部・解析対象・一般実体を表すデータクラスです。
public class InternalParsedEntityData
extends AbstractInternalParsedEntityData
{
public InternalParsedEntityData()
{
}
public void setText(String value)
{
m_replacementText = value;
}
public InternalParsedEntityData getInternalParsedEntity()
{
return this;
}
}
PredefinedEntityDataは内部・解析対象・一般実体の内、定義済み実体 を表す抽象データクラスです。
定義済み実体は、次の機能を持ちます。
フィールド
m_baseList : 置換テキストとして指定できる文字列の候補リスト
m_nomalDeclared: 個別に定義した場合の内部・解析対象・一般実体のデータ(2つ目以降はマージするので1つだけ持つ)
メソッド
setList: 候補リストを設定する
marge : 登録済みデータが定義済み実体のマージ処理(一般実体のマージ処理をせずに定義済み実体はこちらを実行する)
1.内部・解析対象・一般実体データが未だ無い場合
1-1.登録側のデータが内部・解析対象・一般実体でない場合
1-1-1.エラーとする
1-2.登録側のデータが内部・解析対象・一般実体の場合
1-2-1.内部・解析対象・一般実体データとして保存する
1-2-2.候補リストの文字列の場合
1-2-2-1.置換文字列に設定する
1-2-3.候補リストの文字列でない場合
1-2-3-1.エラーとする
2.内部・解析対象・一般実体データが既に有る場合
2-1.内部・解析対象・一般実体データにマージする(定義済み実体でないマージ処理へ)
public class PredefinedEntityData
extends AbstractInternalParsedEntityData
{
//置換テキストの候補
private ArrayList<String> m_baseList;
//個別に定義した場合のデータ
private InternalParsedEntityData m_normalDeclared;
public PredefinedEntityData()
{
m_baseList = new ArrayList<String>();
m_normalDeclared = null;
}
public void setList(ArrayList<String> list)
{
m_baseList = list;
//基本は0番目の要素を置換テキストとする
m_replacementText = m_baseList.get(0);
}
//同名のデータで2つ目以降のデータがきた場合に呼び出す
@Override
public void marge(GeneralEntityData ged)
{
//定義済み実体だけで一般実体宣言はない場合
if (m_normalDeclared == null)
{
InternalParsedEntityData t = ged.getInternalParsedEntity();
//登録データが内部・解析対象一般実体でない場合
if (t == null)
{
//TODO エラー
}
//登録データが内部・解析対象一般実体の場合
else
{
//候補リストにあるか確認する
String txt = t.toString();
boolean hasTxt = m_baseList.contains(txt);
//候補リストにある場合
if (hasTxt)
{
m_replacementText = txt;
}
//候補リストにない場合
else
{
//TODO エラー
}
m_normalDeclared = t;
}
}
//既に内部・解析対象・一般実体宣言がある場合
else
{
m_normalDeclared.marge(ged);
}
}
}
ExternalParsedEntityDataは外部・解析対象・一般実体 を表すデータクラスです。
public class ExternalParsedEntityData
extends GeneralEntityData
{
//システム識別子のリテラル
private String m_systemLiteral;
//公開識別子のリテラル
private String m_pubidLiteral;
public ExternalParsedEntityData()
{
super();
m_systemLiteral = "";
m_pubidLiteral = "";
}
public void setSystemLiteral(String system)
{
m_systemLiteral = system;
}
public void setPubidLiteral(String pubid)
{
m_pubidLiteral = pubid;
}
public String getSystemLiteral()
{
return m_systemLiteral;
}
public String getPubidLiteral()
{
return m_pubidLiteral;
}
}
ExternalUnparsedEntityDataは外部・解析対象外・一般実体を表すデータクラスです。
ただし、記法宣言との関連部分はまだ検討していないため、作成しません。
public class ExternalUnparsedEntityData extends GeneralEntityData
{
private String m_nDataName;
private String m_systemLiteral;
private String m_pubidLiteral;
public ExternalUnparsedEntityData()
{
super();
m_nDataName = "";
m_systemLiteral = "";
m_pubidLiteral = "";
}
public void setNDataName(String name)
{
m_nDataName = name;
}
public void setSystemLiteral(String system)
{
m_systemLiteral = system;
}
public void setPubidLiteral(String pubid)
{
m_pubidLiteral = pubid;
}
}
■GeTableの実装
GeTableは一般実体テーブル(Mapをラッパーするクラス)です。
テーブルは全体で一つなのでシングルトンパターンで作成します。
・初期化時
直接テーブルに定義済み実体を登録する
・構文解析(Visitor)
1.一般実体宣言から実体データを作成する
2.実体データを実体テーブルに登録する
・実体テーブルの登録処理
1.一般実体名(key)を取得する
2.テーブルをkeyで検索し、登録済みデータを取得する
3.登録済みデータが無い場合
3-1.一般実体を登録する
4.登録済みデータが有る場合
4-1.登録済みのデータに合わせて、マージ処理をする
public class GeTable
{
private final static GeTable m_instance = new GeTable();
private Map<String,GeneralEntityData> m_map;
//パラメータ実体の内容を解析しているセクションの間だけtrue
//整形式制約のチェックのための情報
private boolean m_ParametorEntityParseSection;
//外部サブセットを解析しているセクションの間だけtrue
//整形式制約のチェックのための情報
private boolean m_ExtSubsetParseSection;
private GeTable()
{
m_map = new HashMap<String,GeneralEntityData>();
m_ParametorEntityParseSection = false;
m_ExtSubsetParseSection = false;
//定義済み実体を設定する
// lt "<"
// gt ">" または>
// amp "&"
// apos "'" または'
// quot "\"" または"
{
ArrayList<String> list = new ArrayList<String>();
list.add("<");
this.setPredefinedData("lt" , list);
}
{
ArrayList<String> list = new ArrayList<String>();
list.add(">");
list.add(">");
this.setPredefinedData("gt" , list);
}
{
ArrayList<String> list = new ArrayList<String>();
list.add("&");
this.setPredefinedData("amp" , list);
}
{
ArrayList<String> list = new ArrayList<String>();
list.add("'");
list.add("'");
this.setPredefinedData("apos", list);
}
{
ArrayList<String> list = new ArrayList<String>();
list.add("\"");
list.add(""");
this.setPredefinedData("quot", list);
}
}
public static GeTable getInstance()
{
return m_instance;
}
public void notifyParametorEntityParseSectionStart()
{m_ParametorEntityParseSection = true;}
public void notifyParametorEntityParseSectionEnd()
{m_ParametorEntityParseSection = false;}
public void notifyExtSubsetParseSectionStart()
{m_ExtSubsetParseSection= true;}
public void notifyExtSubsetParseSectionEnd()
{m_ExtSubsetParseSection= false;}
public void setData(GeneralEntityData ged)
{
String name = ged.getName();
ged.setParametorDeclaration(m_ParametorEntityParseSection);
ged.setExtSubsetDeclaration(m_ExtSubsetParseSection);
//(既に登録してあるかもしれないので)
//指定のnameでマップからデータを取り出す
GeneralEntityData ged2 = m_map.get(name);
//未だ同名の一般実体が登録してない場合
if (ged2 == null)
{
//一般実体を登録する
m_map.put(name, ged);
System.out.println("Entity "+name+":"+ged);
}
//既に同名の一般実体が登録してある場合
else
{
//マージする
// 定義済み実体以外の場合はエラーとなる
// 定義済み実体の場合はエラーにするかは
// 定義済み実体側の状態で判断する
ged2.marge(ged);
}
}
public GeneralEntityData getData(String name)
{
return m_map.get(name);
}
//定義済み実体を登録する
private void setPredefinedData(String name, ArrayList<String> list)
{
PredefinedEntityData ged = new PredefinedEntityData();
ged.setName(name);
ged.setList(list);
m_map.put(name, ged);
}
}
コメント
コメントを投稿する
SpecialPR