本家「@IT」にはない内容をエンジニアライフで技術紹介するコラム。広く議論する場になることを目指します。

第060回_一般実体テーブル作成処理の実装4

»

前回の続きで、検討したVisitorを実装します。

ExternalIDの実装

ExternalIDのデータ構造を持つクラスExternalIDクラスの実装は次にようにします。
public class ExternalID
{
    //systemLiteral部分
    private String     m_systemLiteral;
    
    //pubidLiteral部分
    private String     m_pubidLiteral;
    
    public ExternalID()
    {
        m_systemLiteral = "";
        m_pubidLiteral = "";
    }
    
    public boolean isEmpty()
    {
        return m_systemLiteral.isEmpty() && m_pubidLiteral.isEmpty();
    }
    
    public void setSystemLiteral(String str)
    {
        m_systemLiteral = StringController.trimAChar(str);
    }

    public void setPubidLiteral(String str)
    {
        m_pubidLiteral = StringController.trimAChar(str);
    }
}

StringControllerの実装

StringControllerはXMLパーサが要求する文字列の制御をするクラスです。
LiteralTokenの文字列は両端の"や'を含みますが、PubidLiteralやSystemLiteral以降、内部で保持するためには不要になるので削除します。

実装は次のようにできます。
public class StringController
{
    //状態をもたず、staticメソッドだけを持つため
    //コンストラクタはprivateで呼び出せないようにする
    private StringController(){}
    
    //先頭と末尾の""や''を取り除く
    public static String trimAChar(String literal)
    {
        return literal.substring(1, literal.length()-1);
    }
}

ExternalIDVisitorの実装

ExternalIDのデータ構造を構築するためのVisitor。

ExternalIDVisitorの実装は次のようになります。
public class ExternalIDVisitor extends SyntaxParserVisitor
{
    private ExternalID m_externalId;
    
    public ExternalIDVisitor()
    {
        m_externalId = new ExternalID();
    }
    
    public ExternalID getExternalId()
    {
        return m_externalId;
    }

    @Override
    public void visit(EbnfPubidLiteralNode n)
    {
        Token token = m_tokenManager.nextToken();
        m_result = token.match(n);
        
        if (m_result)
        {
            String str = token.getString();
            m_externalId.setPubidLiteral(str);
        }
        else
        {
            //何もしない
        }
    }
    
    @Override
    public void visit(EbnfSystemLiteralNode n)
    {
        Token token = m_tokenManager.nextToken();
        m_result = token.match(n);
        
        if (m_result)
        {
            String str = token.getString();
            m_externalId.setSystemLiteral(str);
        }
        else
        {
            //何もしない
        }
    }
}

MakingGeTableVisitorの実装

これまでの子ノード向けのVisitorを使ってGEDeclを解析して、一般実体のシンボルテーブルを作成するVisitorを用意します。

実装は次のようにできます。
public class MakingGeTableVisitor extends SyntaxParserVisitor
{
    //実体のシンボルテーブル
    private static EntityTable m_table
                    = EntityTable.getInstance();

    //巡回データName部分
    private String     m_name;
    
    //巡回データNDataName部分
    private String  m_nDataName;
    
    //巡回データExternalID部分
    private ExternalID m_externalId;

    private GeneralEntityData m_ged;
    
    public MakingGeTableVisitor()
    {
        m_name = "";
        m_nDataName = null;
        
        m_ged   = null;
    }

    @Override
    public void visit(EbnfGEDeclNode n)
    {
        super.visit(n);
        
        if(m_result)
        {
            //テーブルに追加する
            m_table.setData(m_ged);
        }
        else
        {
            //何もしない
        }
    }

    
    @Override
    public void visit(EbnfGeNameNode n)
    {
        Token token = m_tokenManager.nextToken();
        m_result = token.match(n);
        
        if(m_result)
        {
            //処理に成功したので巡回用データに登録する
            m_name = token.getString();
        }
        else
        {
            //何もしない
        }
    }

    @Override
    public void visit(EbnfGeEntityValueNode n)
    {
        EntityValueVisitor v = new EntityValueVisitor();
        
        v.visit(n);
        
        m_result = v.getResult();
        
        if (m_result)
        {
            //一般実体のデータを作成し、巡回データに設定する
            InternalParsedEntityData data
              = new InternalParsedEntityData();
            
            //既に巡回済みのEbnfGeNameNodeの値を設定する
            data.setName(m_name);
            
            String value = v.getValue();
            data.setText(value);
            
            m_ged = data;
        }
        else
        {
            //何もしない
        }
    }

    
    @Override
    public void visit(EbnfExternalDefNode n)
    {
        //子ノードを巡回処理する
        super.visit(n);
                
        //NDataDefがないとき
        if (m_nDataName.equals(""))
        {
            //外部解析対象実体を作成する
            ExternalParsedEntityData data
              = new ExternalParsedEntityData();
            data.setName(m_name);
            data.setExternalId(m_externalId);

            m_ged = data;
        }
        //NDataDefがあるとき
        else
        {
            //解析対象外実体を作成する
            ExternalUnparsedEntityData data
               = new ExternalUnparsedEntityData();
            data.setName(m_name);
            data.setExternalId(m_externalId);
            data.setNDataName(m_nDataName);

            m_ged = data;
        }
    }

    @Override
    public void visit(EbnfGeExternalIDNode n)
    {
        ExternalIDVisitor v = new ExternalIDVisitor();
        n.accept(v);
        
        m_result = v.getResult();
        
        if (m_result)
        {
            m_externalId = v.getExternalId();
        }
    }
    

    @Override
    public void visit(EbnfNDataNameNode n)
    {
        Token token = m_tokenManager.nextToken();
        m_result = token.match(n);
        
        if(m_result)
        {
            //処理に成功したので巡回用データに登録する
            m_nDataName = token.getString();
        }
        else
        {
            //何もしない
        }
    }
}

DoctypedeclVisitorの修正

MakingGeTableVisitorを実行するために、親構文のDoctypedeclVisitorを修整します。
public class DoctypedeclVisitor extends SyntaxParserVisitor
{
    @Override
    public void visit(EbnfGEDeclNode n)
    {
        MakingEntitySymbolTableVisitor v = new MakingEntitySymbolTableVisitor();
        n.accept(v);
    }
}
Comment(0)

コメント

コメントを投稿する