<?xml version="1.0" encoding="UTF-8"?>
<!-- Reviewed: no -->
<!-- EN-Revision: 24249 -->
<sect1 id="zend.tool.framework.architecture">
    <title>アーキテクチャ</title>

    <sect2 id="zend.tool.framework.architecture.registry">
        <title>レジストリ</title>

        <para>
            <property>include_path</property>のどこからでもプロバイダとマニフェストが由来するかもしれないので、
            ツール・チェーンのいろいろな部分へのアクセスを単純化するためにレジストリが提供されます。
            このレジストリはレジストリを認識するコンポーネントに注入されます。
            そして、それから必要に応じてそれは彼らから依存性を引き出すかもしれません。
            レジストリで登録される依存性の多くは、下位-構成要素に特有のリポジトリです。
        </para>

        <para>
            レジストリのためのインターフェースは、以下の定義から成ります。:
        </para>

        <programlisting language="php"><![CDATA[
interface Zend_Tool_Framework_Registry_Interface
{
    public function setClient(Zend_Tool_Framework_Client_Abstract $client);
    public function getClient();
    public function setLoader(Zend_Tool_Framework_Loader_Abstract $loader);
    public function getLoader();
    public function setActionRepository(
        Zend_Tool_Framework_Action_Repository $actionRepository
    );
    public function getActionRepository();
    public function setProviderRepository(
        Zend_Tool_Framework_Provider_Repository $providerRepository
    );
    public function getProviderRepository();
    public function setManifestRepository(
        Zend_Tool_Framework_Manifest_Repository $manifestRepository
    );
    public function getManifestRepository();
    public function setRequest(Zend_Tool_Framework_Client_Request $request);
    public function getRequest();
    public function setResponse(Zend_Tool_Framework_Client_Response $response);
    public function getResponse();
}
]]></programlisting>

        <para>
            レジストリが管理するいろいろなオブジェクトは、それらに該当する部分で論じられます。
        </para>

        <para>
            レジストリを認識しなければならないクラスは、
            <classname>Zend_Tool_Framework_Registry_EnabledInterface</classname>を実行しなければなりません。
            このインターフェースは、単に対象クラスだけでレジストリの初期化を可能にします。
        </para>

        <programlisting language="php"><![CDATA[
interface Zend_Tool_Framework_Registry_EnabledInterface
{
    public function setRegistry(
        Zend_Tool_Framework_Registry_Interface $registry
    );
}
]]></programlisting>
    </sect2>

    <sect2 id="zend.tool.framework.architecture.providers">
        <title>プロバイダ</title>

        <para>
            <classname>Zend_Tool_Framework_Provider</classname>は、
            フレームワークの機能または「能力」面を表現します。
            基本的に、<classname>Zend_Tool_Framework_Provider</classname>は
            「プロバイダ」をもたらすために必要なインターフェース、
            または<classname>Zend_Tool_Framework</classname>ツール・チェーン内で呼ぶことができて、
            使うことができる若干のツーリング機能を提供します。
            このプロバイダ・インターフェースを実装することの割り切った性質によって、
            開発者は機能/能力を「ワンストップサービス」で
            <classname>Zend_Tool_Framework</classname>に加えることができます。
        </para>

        <para>
            プロバイダ・インターフェースは空のインターフェースで、メソッドを強制しません。
            （これは、マーカ・インターフェース・パターンです）:
        </para>

        <programlisting language="php"><![CDATA[
interface Zend_Tool_Framework_Provider_Interface
{}
]]></programlisting>

        <para>
            あるいは、もし望めば、<classname>Zend_Tool_Framework_Registry</classname>に
            アクセスできるようにする基底（または抽象）プロバイダを実装できます。:
        </para>

        <programlisting language="php"><![CDATA[
abstract class Zend_Tool_Framework_Provider_Abstract
    implements Zend_Tool_Framework_Provider_Interface,
               Zend_Tool_Registry_EnabledInterface
{
    protected $_registry;
    public function setRegistry(
        Zend_Tool_Framework_Registry_Interface $registry
    );
}
]]></programlisting>

    </sect2>

    <sect2 id="zend.tool.framework.architecture.loaders">
        <title>ローダ</title>

        <para>
            ローダの目的は、<classname>Zend_Tool_Framework_Provider_Interface</classname>か
            <classname>Zend_Tool_Framework_Manifest_Interface</classname>を実装するクラスを含む
            プロバイダとマニフェスト・ファイルを見つけることです。
            一旦これらのファイルがローダによって見つかると、
            プロバイダはプロバイダ・リポジトリにロードされ、
            マニフェスト・メタデータはマニフェスト・リポジトリにロードされます。
        </para>

        <para>
            ローダを実装するために、以下の抽象クラスを拡張しなければなりません:
        </para>

        <programlisting language="php"><![CDATA[
abstract class Zend_Tool_Framework_Loader_Abstract
{

    abstract protected function _getFiles();

    public function load()
    {
        /** ... */
    }
}
]]></programlisting>

        <para>
            <methodname>_getFiles()</methodname>メソッドは、ファイル（絶対パス）の配列を返さなければなりません。
            Zend Frameworkで供給されるビルトイン・ローダは、インクルードパス・ローダと呼ばれます。
            デフォルトで、ツーリング・フレームワークは、
            プロバイダまたはマニフェスト・メタデータ・オブジェクトを含むかもしれないファイルを見つけるために、
            include_pathベースのローダを使います。
            他のオプションが全く無くても、
            <classname>Zend_Tool_Framework_Loader_IncludePathLoader</classname>はインクルードパスの中で
            <filename>Mainfest.php</filename>、<filename>Tool.php</filename>または<filename>Provider.php</filename>で
            終わるファイルを探します
            <classname>Zend_Tool_Framework_Loader_Abstract</classname>の<methodname>load()</methodname>メソッドによって一旦見つかると、
            それらがサポートされたインターフェースのいずれかを実装するかどうか判定するためにそれらはテストされます。
            もし実装していれば、見つかったクラスのインスタンスがインスタンス化されます、
            そして、それは固有のリポジトリを付加されています。
        </para>

        <programlisting language="php"><![CDATA[
class Zend_Tool_Framework_Loader_IncludePathLoader
    extends Zend_Tool_Framework_Loader_Abstract
{

    protected $_filterDenyDirectoryPattern = '.*(/|\\\\).svn';
    protected $_filterAcceptFilePattern = '.*(?:Manifest|Provider)\.php$';

    protected function _getFiles()
    {
        /** ... */
    }
}
]]></programlisting>

        <para>
            ご覧の通り、インクルードパス・ローダは、<varname>$_filterAcceptFilePattern</varname>にマッチし、
            <varname>$_filterDenyDirectoryPattern</varname>にマッチしないファイルを求めて、
            すべてのinclude_pathsを検索します。
        </para>
    </sect2>

    <sect2 id="zend.tool.framework.architecture.manifests">
        <title>マニフェスト</title>

        <para>
            要するに、マニフェストはプロバイダ・リポジトリにどんなさらなるプロバイダでもロードする役割を果たしうるばかりではなく、
            どんなプロバイダまたはクライアントにとってでも有用である、指定された、または任意のメタデータを含みます。
        </para>

        <para>
            空の<classname>Zend_Tool_Framework_Manifest_Interface</classname>を実装して、
            <classname>Zend_Tool_Framework_Manifest_Metadata</classname>を実装する
            オブジェクトの配列を返す<methodname>getMetadata()</methodname>メソッドを提供しさえすれば、
            メタデータをマニフェスト・リポジトリにもたらすことができます。
        </para>

        <programlisting language="php"><![CDATA[
interface Zend_Tool_Framework_Manifest_Interface
{
    public function getMetadata();
}
]]></programlisting>

        <para>
            下記で定義されたローダによって、
            メタデータ・オブジェクトはマニフェスト・リポジトリ(<classname>Zend_Tool_Framework_Manifest_Repository</classname>)にロードされます。
            すべてのプロバイダがプロバイダ・リポジトリにロードされるとわかったあと、マニフェストは処理されます。
            これによって、何が現在プロバイダ・リポジトリ内部にあるかに基づくメタデータ・オブジェクトをマニフェストは作成できます。
        </para>

        <para>
            メタデータを記述するために用いることができる
            多少の異なるメタデータ・クラスがあります。
            <classname>Zend_Tool_Framework_Manifest_Metadata</classname>は、
            基底メタデータ・オブジェクトです。
            以下のコード・スニペットによってわかるように、
            基底メタデータ・クラスは事実上かなり軽量で抽象的です:
        </para>

        <programlisting language="php"><![CDATA[
class Zend_Tool_Framework_Metadata_Basic
{

    protected $_type        = 'Global';
    protected $_name        = null;
    protected $_value       = null;
    protected $_reference   = null;

    public function getType();
    public function getName();
    public function getValue();
    public function getReference();
    /** ... */
}
]]></programlisting>

        <para>
            より分化したメタデータを記述するために同様に他のビルトイン・メタデータ・クラスがあります:
            <classname>ActionMetadata</classname>及び<classname>ProviderMetadata</classname>。
            これらのクラスは、アクションまたはプロバイダのいずれかに特有なメタデータをより詳細に記述する助けになります。
            そして、参照はそれぞれアクションまたはプロバイダへの参照であることが期待されます。
            これらのクラスは、以下のコード・スニペットで記述されます。
        </para>

        <programlisting language="php"><![CDATA[
class Zend_Tool_Framework_Manifest_ActionMetadata
    extends Zend_Tool_Framework_Manifest_Metadata
{

    protected $_type = 'Action';
    protected $_actionName = null;

    public function getActionName();
    /** ... */
}

class Zend_Tool_Framework_Manifest_ProviderMetadata
    extends Zend_Tool_Framework_Manifest_Metadata
{

    protected $_type = 'Provider';
    protected $_providerName  = null;
    protected $_actionName    = null;
    protected $_specialtyName = null;

    public function getProviderName();
    public function getActionName();
    public function getSpecialtyName();
    /** ... */
}
]]></programlisting>

        <para>
            これらのクラスでの'Type'は、
            オブジェクトが責を負うべきメタデータのタイプを記述するのに用いられます。
            <classname>ActionMetadata</classname>のケースでは、タイプは'Action'です。
            そして逆に、<classname>ProviderMetadata</classname>の場合は、タイプは'Provider'です。
            これらのメタデータ・タイプは、
            それらがこの新しいメタデータで参照しているオブジェクト(<methodname>getReference()</methodname>)だけでなく、
            それらが記述している「もの」についても、さらなる構造化情報を含みます。
        </para>

        <para>
            基底<classname>Zend_Tool_Framework_Manifest_Metadata</classname>クラスを拡張して、
            クラス/オブジェクト・ローカル・マニフェストを通してこれらの新しいメタデータ・オブジェクトを返しさえすれば、
            あなた自身のメタデータ・タイプを構築できます。
            これらのユーザー・ベースのクラスは、マニフェスト・リポジトリの中に残ります
        </para>

        <para>
            もし、これらのメタデータ・オブジェクトがリポジトリならば、
            リポジトリでそれらを探すために利用できる２つの異なるメソッドがあります。
        </para>

        <programlisting language="php"><![CDATA[
class Zend_Tool_Framework_Manifest_Repository
{
    /**
     * 検索するメソッドを使うために、
     * $searchPropertiesはマニフェストの範囲内でマッチさせたい
     * キーと値のペアの名前と値を含まなければなりません。
     *
     * 例:
     *     $manifestRepository->findMetadatas(array(
     *         'action' => 'Foo',
     *         'name'   => 'cliActionName'
     *         ));
     *
     * 値'Foo'と名前'action'でキーを持つどんなメタデータ・オブジェクトも見つけます。
     * そして、キーは'cliActionName'の'name'値と名づけられました。
     *
     * 注意:
     * 検索基準の中に存在するが、オブジェクトに現れない名前と値のペアを除外するか、
     * または含むために、$includeNonExistentPropertiesにブール値を渡してください
     */
    public function findMetadatas(Array $searchProperties = array(),
                                  $includeNonExistentProperties = true);

    /**
     * どれくらいが返されたかに関係なく、
     * マッチしている検索基準のうちのちょうど1つを以下は返します。
     * マニフェストの最初の1つは、何が返されるかということです。
     */
    public function findMetadata(Array $searchProperties = array(),
                                 $includeNonExistentProperties = true)
    {
        $metadatas = $this->getMetadatas($searchProperties,
                                         $includeNonExistentProperties);
        return array_shift($metadatas);
    }
}
]]></programlisting>

        <para>
            上記のサーチ方式を見ると、シグニチャはとても柔軟に検索することを許します。
            メタデータ・オブジェクトを見つけるために、
            制約にマッチする配列を単に配列によって渡してください。
            データがプロパティ・アクセッサ
            （オブジェクト・メタデータの上で実装される<methodname>getSomething()</methodname>メソッド）
            によってアクセスできるならば、
            それは「見つかった」オブジェクト・メタデータとしてユーザーへ渡されます。
        </para>
    </sect2>

    <sect2 id="zend.tool.framework.architecture.clients">
        <title>クライアント</title>

        <para>
            クライアントは、<classname>Zend_Tool_Framework</classname>システムと
            ユーザーまたは外部ツールとの橋渡しをするインターフェースです。
            クライアントは、すべての形とサイズに伝わることができます:
            <acronym>RPC</acronym>エンドポイント、コマンド・ライン・インタフェースまたはウェブ・インターフェースさえ。
            Zend_Toolは、<classname>Zend_Tool_Framework</classname>システムと相互に作用するための
            デフォルト・インターフェースとして、コマンド・ライン・インタフェースを実装しました。
        </para>

        <para>
            クライアントを実装するためには、以下の抽象クラスを拡張する必要があります。:
        </para>

        <programlisting language="php"><![CDATA[
abstract class Zend_Tool_Framework_Client_Abstract
{
    /**
     * このメソッドは、カスタム・ローダ、リクエストとレスポンス・オブジェクトを構成して、
     * セットするために、クライアント実装によって実装されなければなりません。
     *
     * (必須ではありませんが、提案されます)
     */
    protected function _preInit();

    /**
     * このメソッドは解析するクライアント実装によって実装されなければなりません。
     * リクエスト・オブジェクト・アクション、
     * プロバイダ及びパラメータ情報を準備しなければなりません。
     */
    abstract protected function _preDispatch();

    /**
     * このメソッドは、レスポンス・オブジェクトを出力して、
     * それをツーリング・クライアントに（クライアントに特有の手段で）返すために、
     * クライアント実装によって実装されなければなりません。
     *
     * (必須ではありませんが、提案されます)
     */
    abstract protected function _postDispatch();
}
]]></programlisting>

        <para>
            ご覧の通り、そこで、1つのメソッドはクライアントの必要を満たすことを要求されます。
            （他の２つは提案されます）
            初期化、前処理と後処理
            コマンド・ライン・クライアントが動く方法についてより深く研究するには、
            <ulink
                url="http://framework.zend.com/svn/framework/standard/branches/release-1.8/library/Zend/Tool/Framework/Client/Console.php">ソースコード</ulink>
            を見てください。
        </para>

    </sect2>
</sect1>
