プログラミングやる前に先お風呂はいっちゃいなさい

109月/090

独自メタデータタグを作る方法

Firefoxに初めて、並々ならぬ殺意を覚えた。

なに、俺が珍しくブログ書いてる時に何の前触れも無く落ちやがる。

もう、全部消えたやないけ!

泣くぞ?俺は泣くと手が付けられないんだからな!?

(ノ_<、)

恨み言はこれくらいにして、書き直します。

いいんだ、どうせ僕のポストなんて大宇宙の意思に比べたら全然小さいんだ。だから別に消えても世界は同じように回るんだ。

独自メタデータタグを作る方法

前回のポストでメタデータタグがあまりに便利だったので、オレオレメタデータタグが作りたくなった。以上。

投げやり?苦情はFirefoxに言ってくれ。

そんなこんなで、独自のメタデータタグを作る方法を調べてみました。

Annotating ActionScript Classes with Custom Metadata + Simple ORM Framework for AIR
http://coenraets.org/blog/2007/10/annotating-actionscript-classes-with-custom-metadata-simple-orm-framework-for-air/

AS3で独自メタデータの保持
http://www.be-interactive.org/?itemid=202

上のサイトは英語です。でも、独自メタデータをどうやって使うかがサンプルコードを見ると分かります。
describeTypeっていう関数を使って、インスタンスからクラス構造をXMLで取得できるので、そのXMLを解析すればメタデータタグの情報が取得できるってわけです。

下のサイトはBeInteractive!のyossyさんが独自メタデータタグを使ったコードのビルド方法について書かれている記事です。
これを参考にビルドしてみました。

サンプル

Player.as

package me.rkome.da.labs
{
    public class Player
    {
        public function Player()
        {
        }

        private var _test:String;

        [DarkOmeme("programmer")]
        public function set test(val:String):void
        {
            _test = val;
        }
        public function get test():String
        {
            return _test;
        }
    }
}

サンプルとしてこんなクラスを作ってみました。クラス名は適当です。本当は理由があったんだけど、迷宮入りです。Firefoxに言ってください。

testってプロパティにDarkOmemeって独自メタデータを付加して、値として"programmer"という文字列を渡しています。

さて、ではこいつのインスタンスを実際にdescribeTypeして見ましょう。

MetadataApp.mxml

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" creationComplete="onCreationComplete()">
    <mx:Script>
        <![CDATA[
            import flash.utils.describeType;
            import me.rkome.da.labs.Player;
            private function onCreationComplete():void
            {
                var player:Player = new Player();
                trace(describeType(player));
            }
        ]]>
    </mx:Script>
</mx:Application>

こんなアプリケーションを作ってみました。って事でビルドしてみましょう。

ビルドオプションはこんな感じ。

ビルドオプション

さて、結果はどう表示されるかというと。こんなん出ました。

<type name="me.rkome.da.labs::Player" base="Object" isDynamic="false" isFinal="false" isStatic="false">
  <extendsClass type="Object"/>
  <accessor name="test" access="readwrite" type="String" declaredBy="me.rkome.da.labs::Player">
    <metadata name="DarkOmeme">
      <arg key="" value="programmer"/>
    </metadata>
  </accessor>
</type>

オー、チャントDarkOmemeメタデータタグガフカサレテイルノガワカリマスネー。スゲーヤ。知ってるけどな!さっきやったから!

まー、あとはこのXMLを解析して煮るなり焼くなり、しましょうって事ですね。

次に、Flexでは有名なメタデータタグである[Bindable]を付加して同じようにdescribeTypeしてみました。そしたら、少し驚きだったんですよ。さっきね!

<type name="me.rkome.da.labs::Player" base="Object" isDynamic="false" isFinal="false" isStatic="false">
  <extendsClass type="Object"/>
  <implementsInterface type="flash.events::IEventDispatcher"/>
  <method name="addEventListener" declaredBy="me.rkome.da.labs::Player" returnType="void">
    <parameter index="1" type="String" optional="false"/>
    <parameter index="2" type="Function" optional="false"/>
    <parameter index="3" type="Boolean" optional="true"/>
    <parameter index="4" type="int" optional="true"/>
    <parameter index="5" type="Boolean" optional="true"/>
  </method>
  <method name="dispatchEvent" declaredBy="me.rkome.da.labs::Player" returnType="Boolean">
    <parameter index="1" type="flash.events::Event" optional="false"/>
  </method>
  <method name="hasEventListener" declaredBy="me.rkome.da.labs::Player" returnType="Boolean">
    <parameter index="1" type="String" optional="false"/>
  </method>
  <method name="removeEventListener" declaredBy="me.rkome.da.labs::Player" returnType="void">
    <parameter index="1" type="String" optional="false"/>
    <parameter index="2" type="Function" optional="false"/>
    <parameter index="3" type="Boolean" optional="true"/>
  </method>
  <method name="willTrigger" declaredBy="me.rkome.da.labs::Player" returnType="Boolean">
    <parameter index="1" type="String" optional="false"/>
  </method>
  <accessor name="test" access="readwrite" type="String" declaredBy="me.rkome.da.labs::Player">
    <metadata name="Bindable">
      <arg key="event" value="propertyChange"/>
    </metadata>
    <metadata name="DarkOmeme">
      <arg key="" value="programmer"/>
    </metadata>
  </accessor>
</type>

なんと、IEventDispatcherが自動的に実装されてるじゃあ、ありませんか!自動的に!

どうやら、調べてみるとこれはmxmlc(Flexのコンパイラ)がメタデータタグを見つけてコードを自動生成するらしくて、これみたいなメタデータタグは今回の方法では作れないようです。

まあ、mxmlcはオープンソースなんで、オレオレmxmlcを作りましょうって事ですね。わかります。

今回はそこまで深入りしませんでした。

ただ、一応、mxmlcのソース(Javaで書かれている)を見に行ったんですが、どうやらコードを自動生成する部分はJavaでない、何やら良く分からないスクリプトで書かれていました
多分、テンプレートエンジンみたいのを備えていて、そいつに通すと自動生成されるんだと思います。

さて、本当はmxmlcのメタデータタグみたいなのが作れるといいなあと思ったんですが、思ったよりヘビーなんでこの方法で何か出来ないか模索してみることにします。

最後に。

Firefoxさんいつもお世話になっています。ありがとう。