yamicha.com's Blog - Presented by yamicha.com
Blog yamicha.com's Blog - 2017/11 の記事
[1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [11] [12] [13] [14] [15] [16] [17] [18] [19] [20] [21] [22] [23] [24] [25] [26] [27] [28] [29] [30]

yamicha.com's Blog
 諸事情により、現在更新休止中。ご了承ください。もし今後ブログを再開することがあるとすれば、その際にはこのブログスクリプトではなく、新しく開発したものによるかもしれません。
 当ブログ管理者についてはこちらをご参照。
開発魔法(737)
社会問題(733)
お知らせ(11)
質問・バトン回答(15)
ゲスト出演(8)
経済・知的財産(150)
ゲーム開発(182)
[Ada] 勝手に補足
- Note
- 金配りの次の一手


- Endless Ultimate Diary
- 銃世界

漢字バトン
- うるる雑記帳
- 漢字接力棒

ツキアイゲノムバトン
- ブログ@うにうに画像倉庫
- あぶ内閣

縺イ縺セ縺、縺カ縺励ヰ繝医Φ
- 月夜のボヤキ
- 騎士サーラバトン
パスワードを使う
名無し (2012/02/27)


開発者解放裁判
yamicha.com (2010/03/14)
Winnyに関しては、私も「純白」とまでは考えておりませんし、使用し..

開発者解放裁判
通りすがり (2010/03/08)
winnyに関しては「ダウンロードソフト板」なんてところを拠点に開発..

新型インフルエンザの恐怖
いげ太 (2009/11/03)
> C#などの「int Some(int , int)」は、F#では「(int * int) ->..

時効に関する思考
yamicha.com (2009/08/31)
>いげ太さんコメントありがとうございます。手元にドキュメントが少..
Homepage
Blog Top
Normal View
List View
Search
Calendar
Comment List
Trackback List
Blog RSS
Send Trackback
Phone Mode
Administrator
yamicha.com
Blog
るううるる。
Source
法令データ提供システム
FindLaw
Development
Java2 Platform SE 6
Java EE 6 API
MySQL Developer Zone
PHP Reference
MSDN Library
Ada Reference Manual
Objective Caml
Python Documentation
Erlang
Prolog Documents
カテゴリ表示
 カテゴリ 経済・知的財産 に当てはまるもののみを表示します。

 存在する記事 150 件の中から 1-5 件を表示しています。
無理知国災再び
2010/08/02(Mon)01:36:31
 ねじれ国会、小沢氏の暗躍など波乱含みの民主党ですが、ここで見逃せない動きが登場してきました。国民新党の亀井氏が、菅氏に対して無利子非課税国債の導入を進言したというのです。今のところ菅氏は「勉強する」とだけ返答し、まだ具体的な話は出ていないようですが、今後の民主党及び菅氏の対応によっては導入がなされる可能性も否定できません。なお、同案は麻生政権時にも導入が検討されましたが、その際には見送りとなりました。
 亀井氏は消費税増税に慎重な立場を取っており、無利子非課税国債によって増税をせずに財政再建に必要な財源を手に入れようとのもくろみがあるようですが、あまりにも安易な帳尻合わせの一言に尽きます。相続税の免除自体にも問題点が多く、消費税増税には国民からの反発を受けても、相続税免除を引き換えにした借金であれば怒らないと考えているのであれば、国民をバカにするにもほどがあります
 相続税について詳しく知りたい方には相続税法を読んでいただくとして、要点を簡単にかいつまんで記述すれば、まず相続資産には最低でも6000万円(基本5000万円に加え、相続を受ける者1人につき1000万円)の控除がなされ、それを超過した部分に対して相続税がかかります。また、税率も金額が少ないうちは10%に過ぎず、最高税率である50%が適用されるのは課税部分のうち3億を超過した部分のみであるなど、極めて累進性の高いものとなっています。すなわち、大半の一般家庭にはあまり縁がなく、資産家の相続には大きな影響を持つ税であるといえます。
 無利子非課税国債は、この税を免除あるいは軽減することと引き換えに無利子での借金を行うものです。わざわざ言うまでもありませんが、これは相続税にあまり縁がない一般家庭にとってはメリットのない代物である一方、大量の相続税を取られる資産家にとっては明らかに有利な政策です。同債が実際に運用されるとなれば、不公平感を軽減するために一定の制限は設けられるはずですが、いかに制限を強化したとしても大量の相続税支払いが必要な層に対してのみ有利な選択肢を提供することに変わりはありません。
 また、世の中の大半の税は「富の再分配」の意味を多分に含んでおり、特に相続税は単に収入を分配するという意味合いだけでなく、「金持ちの子は金持ち」という富の偏在・格差の固定化を軽減する機能も併せ持っています。格差の固定化は不公平感を増大し、社会から活力を奪ってしまう恐れもある重大な問題ですが、果たして亀井氏はそこまで考えた上でこのような案を提示しているのでしょうか。
 また、無利子非課税国債は確かに「国民資産」を無利子で活用できる方法ではありますが、借金はあくまで借金です。そもそも「無利子」という言葉が曲者で、無利子を我慢してもなお十分な利益のある条件でなければ同債を買う人などいないことを忘れてはいけません。同債分の財源を上手く弱者に振り向けられれば、弱者にもメリットのある政策にならないとは言い切れませんが、無利子とはいえ結局は借金であること、無利子と引き換えにそれ以上のメリットを提供しなければならないことなどを考えれば、単なるおためごかしに終わる可能性が極めて高いといえるでしょう。
 すなわち、無利子非課税国債は消費税に比べて負担が軽いようでいて、簡単に検証するだけでもこれだけの重大かつ多量の問題が存在し、逆進的であるとはいえ課税額が購買力にある程度比例し、しかも生活用品の減免や補助などによる弱者の負担軽減を図る余地がある消費税に比べ、公平あるいは軽負担であるとは到底いえません。ある意味、国民に見えにくいところでコソコソと細工をして帳尻を合わせようとする無利子非課税国債より、批判覚悟の消費税の方がまだ正当であるとさえいえます。
 さらに何より不安なのは、仮に無利子非課税国債が導入された場合、実際には「明日の相続税」をツケにしたものでありながら、「今日」の便利さのために際限がなくなってしまいかねない点です。特に亀井氏は消費税増税をせずに同債を発行すべしと主張していますが、これでは収支は当面プラスには近づきません。そうして無利子の借金に慣れてしまうと、無利子の借金返済のために泥沼的に無利子の借金を行い、気づいた時には国内資産は枯渇し、しかも格差が対処のしようがないほどに固定化され、社会は活気・流動性をなくし、国民の不公平感も極限まで増大するという、最悪としか形容しようのない状況にも陥りかねません。
 そして、単に亀井氏が無利子非課税国債を計画しているだけであれば、亀井氏の妄想に過ぎないとして片付けることもできますが、もし菅氏が乗り気になれば妄想では済まされません。麻生政権でもこの案が出ていたように、自民党内にもこれを主張する者は存在し、両党の協力によって実現される可能性が否定できないためです。
 言うまでもなく、菅氏はこの案を安易に採用すべきではありません。数々の短所からして好ましい案とはいえませんし、仮にどうしても実現する必要があるとしても、多くの短所を上手く回避する綿密な計画が必要となるためです。そして、この案を本気で検討している姿勢を見せようものなら、本問題は確実に小沢氏の暗躍、消費税増税して法人税減税問題に次ぐ菅氏・民主党の泣き所となるでしょう。
 亀井氏や国民新党の立場はともかくとして、菅氏は責任ある与党として消費税増税の話もしており、それ自体は悪いことではありません。しかし、それとセットの法人税減税に関しては、かなりの批判があると見るや、あわてて「優遇措置廃止による財源捻出」に方針転換し、さらには突如として所得税の最高税率見直しも検討、最後には「消費税を上げる際には改めて信を問う」と大幅に主張が後退するなど、氏の税制発言はひたすらに混迷を深め、参院選敗北の原因となりました。この上さらに「消費税を上げずに無利子非課税国債」などといい加減かつ政権与党として無責任なことが言えるわけがありませんし、かといって消費税増税で弱者にも少なからぬ負担を求め、その一方で相続税は優遇するなどと言い出せば、民主党がいっそうの失望を集めるのは確実です。しかも、民主党や菅政権がこのようなことを言い出したとなれば、所得税最高税率引き上げ、法人税の優遇措置廃止による財源捻出なども、消費税への批判をかわすための口約束と判断されても仕方がありません。
 無利子非課税国債問題に関しては、負担や問題点が消費税よりは見えにくい上、問題を理解するためには相続税法や富の分配に関する若干の知識が必要となり、政治家の間には「消費税より通すのが楽」という意識があるのかもしれません。しかし、国民をあまり侮ってばかりいると、じきに手痛いしっぺ返しを受けることになるでしょう。

 このほどGlassFish v3 PreviewをOracle GlassFish v3 Open Sourceに取り替えてみました。昨年の間のPreviewとその後のPreviewでは全くといって良いほど変わっており、昨年のPreviewではJPA 2.0の機能をほとんど使えなかったばかりか、Adminコンソールすら相当貧弱であったところを、後期PreviewはJava EE 6の仕様をほとんど満たしたものとなっていましたが、それだけに正式版にはさほど目新しさがありません。
 しかし、ドキュメントにOracle GlassFish Server 3.0.1 Scripting Framework Guideなる怪しい項目が加わっており、何とJRuby on Rails、Grails、Jython、PHPの使い方が書かれています。PHPに関しては、以前にやや面倒なBridgeを使ったことがありましたが、先のドキュメントによれば「warをダウンロードして配備する」というお手軽仕様である模様です。Java EEでPHPが平然と動く(しかも公式ドキュメントに記載)のは面白そうですので、動かしてみないわけにはいきません。
 以下、極めて簡単に動かす手順の覚え書きです。ドキュメントに記載されている方法よりいい加減ですが、デバッグや実験には便利です。
  1. このサイトからQuercusをダウンロード。表記は"war"だが、なぜかzip形式で入手できる。
  2. これを任意の場所に解凍。ディレクトリ名には分かりやすいものを使用。Java EEやGlassFish専用の作業場ディレクトリがあるなら、そこに解凍するのがよい。
  3. Adminコンソールを開き、これをディレクトリごとデプロイ
  4. 後は"Launch"(言語が日本語なら「起動」)。成功メッセージが表示されれば成功。Quercusはindex.phpの内容をパースして表示している。
 Java EEの上にPHPが乗っかっているような操作性で扱えて分かりやすいです。
 index.phpの動作が確認できたら、次は自分のPHPコードを動かしてみなくては話になりません。以下のような適当なコードをhello.phpとして保存し、
<html>
<head>
<title>Hello Quercus</title>
</head>
<body>

<ul>
<?php
$arr = array("GlassFish" , "Quercus" , "PHP");

foreach($arr as $a){
	print "<li>Hello <b>$a</b>.</li>";
}
?>
</ul>

</body>
</html>
 「(サーブレットのURL)/hello.php」を開いてみると、無事にhello.phpの内容がパースされて表示されました。やはり本物のPHPを動かしているような感覚で、なかなか使いやすそうです。
 これでひとまずPHPが動くのは分かりましたが、それではフォーム値はPHPのやり方で処理できるのでしょうか。実際に試してみました。
<html>
<head>
<title>Hello Quercus</title>
</head>
<body>

Q:I like Spam.<br />
Q:I love Spam.<br />
Q:Spam is very delicious.<br />
Q:Do you like Spam?<br />

<?php
if(isset($_POST["answer"]) && $_POST["answer"] != ""){
	print "A:<b>" . $_POST["answer"] . "</b>";
}else{
	print <<<EOF
<form method="POST">
Your answer: <input type="text" name="answer" size="20">
<input type="submit" value="Say">
</form>
EOF;
}
?>

</body>
</html>
 適当に入力して送信してみて、入力したテキストが表示されれば成功です。
Q:I like Spam.
Q:I love Spam.
Q:Spam is very delicious.
Q:Do you like Spam?
A:I DON'T LIKE SPAM!
 どうやら引数も普通のPHPと同様に処理できるようです。
 他にもPHPには様々な機能があり、$_FILEの扱い、チェックボックスの"name[]"のテクニックなどがQuercusでも使えるかは気になるところですので、この辺の調査も必要そうです。
カテゴリ [開発魔法][社会問題][経済・知的財産] [トラックバック 0][コメント 0]

税制大菅波
2010/07/04(Sun)23:07:14
 税制発言で混迷に陥っている民主党ですが、今度は菅氏自ら所得税の最高税率引き上げを検討する考えを示しました。消費税に関しては、所得次第での還付措置と生活必需品の税率軽減の考えを表明しているものの、これも発言が一定していないとの批判を浴びています。また、法人税は「課税対象を広げれば、法人税収の総額を変えないことは可能」であると述べ、外部から財源を持ち込まない考えを示しています。
 いずれも案としては妥当であったり、諸外国で実際に導入・運用されていたりするものばかりですが、あまりにも行き当たりばったりであると言わざるを得ません。所得税の最高税率をかつての水準に近づけたり、法人税の課税を組み替えたりすること自体には検討の余地がありますが、このタイミングで行き当たりばったりに出されては、消費税を上げる際の批判をかわすためのポーズで、本当に実現する気はないのではないかと不安を持たれても仕方がありません。
 仮にこれらの案を出すだけ出しておいて、消費税だけ上げてこれらは実施しなかったとなれば、もはや詐欺以外の何者でもありません。特に法人税については、「消費税を上げて法人税を下げる」行為が批判を浴びるのは当然ですが、この批判を避けるために考えもなしに法人税内部での組み換えを主張し、後から産業界の主張に負けて撤回したり、または案の定失敗して消費税財源による穴埋めを余儀なくされたとなれば、冗談では済まされません。
 ある税を増税しても、それが他の減税によって相殺されれば、結果的に国の歳入は直接的には増えないわけですから、税制というものは一体的に論じる必要があります。したがって、仮に民主党が消費税増税と同時に「法人税減税は法人税の組み換えにより行う」ことと「所得税の最高税率引き上げ」を主張するのであれば、これらはセットでなくてはいけません。そして、行うと主張したからには必ず行わなくてはなりません。他方、もし所得税の最高税率引き上げや法人税減税の自己完結をする気がない、あるいはそれをするとは限らないのであれば、「消費税は上げるが、他はしないかもしれない」と明確に宣言しなければなりません。
 ことに法人税の場合、「内部で収支を合わせる」必要があるわけですから、行き当たりばったりの案で実施できるとは限りません。法人税減税の是非はともかくとして、問題のある優遇措置廃止による不公平性の解消は悪いことではありませんが、優遇対象額や産業の変動なども考えずにいい加減な制度改変を行えば、どのみち消費税から資金を充填しなくてはならなくなります。消費税増税で批判を浴びたからと、考えもなしに批判をそらす案を公表するのではなく、しっかり検証してもらわなくては困ります。
 消費税の税率軽減や還付措置については、実際に多くの諸外国でも採用されており、増税の際には導入を検討する価値は十分にあります。しかし、それでも消費税というものが本質的に逆進性の強い税である以上、増税するなら社会福祉など逆進性を軽減できる用途に充てることが大前提です。いくら軽減措置を導入したからといって、それを所得税や相続税の軽減などといった累進税の減税、または法人税減税など、逆進性を軽減できない用途に用いる大義名分ができるわけではありません。
 また、軽減措置を充実させれば税収も減少し、結局は消費税率を高く設定しなければならなくなったり、早めに次なる増税を行わなければならなくなったりといった本末転倒な事態を招くため、軽減にも限界があります。そのような面からも、消費税は社会福祉に使用して逆進性の問題を軽減する前提は揺らぎません。繰り返しますが、「逆進性軽減措置を導入さえすれば、消費税に固有の問題を考える必要がなくなる」わけではありません
 菅氏の「消費税増税」「自己完結による法人税減税」「所得税最高税率引き上げ」の税制3点セットは、それなりに面白い提案であるとはいえるでしょう。しかし、あまりに行き当たりばったりの提案、かつ消費税増税が批判されているタイミングとあって、後の2つを本当に実行する気があるのか疑問を抱かざるを得ない状態となっています。消費税増税の批判をかわすためではなく、本当にそれをする気があるのなら、氏はそれを明確に宣言する必要があります。一方、実際には行う気がない、または行うとは限らないのであれば、氏はそれを明確に宣言しなくてはなりません。

 JPAであえて@Embeddedを使用する理由といえば、何らかの汎用性のあるコードの再利用に他なりませんが、今回は以前のTitle.java及びRuby.javaを用いたコードを作成してみます。
 前回作成したのは辞書らしきものでしたが、今回作成するのは名簿とします。名前はまず苗字でソートし、さらに名前でソートするものとします。したがって、人物データはTitle型のプロパティを2つ(姓・名)持つことになります。
/WEB-INF
 /classes
  /com
   /yamicha
    /namelist
     Title.java
     Ruby.java
     Person.java
     Category.java
     NameListAccess.java
     NameListServlet.java
  /META-INF
   persistence.xml
 persistence.xmlは例によって変更の必要がありません。
<?xml version="1.0" encoding="UTF-8"?>

<persistence version="1.0"
xmlns="http://java.sun.com/xml/ns/persistence">
<persistence-unit name="MySQL" transaction-type="JTA">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<jta-data-source>jdbc/MySQL</jta-data-source>
<properties>
<property name="eclipselink.jdbc.driver"
value="com.mysql.jdbc.Driver" />
<property name="eclipselink.ddl-generation" value="create-tables" />
<property name="eclipselink.ddl-generation.output-mode" value="database" />
<property name="eclipselink.target-database" value="MySQL" />
<property name="eclipselink.logging.level" value="FINE"/>
</properties>
</persistence-unit>
</persistence>
 Title.javaとRuby.javaのコードは前回と全く同じです(パッケージ名だけは変えてあります)。
// Ruby.java
package com.yamicha.namelist;

import javax.persistence.*;

@Embeddable public class Ruby
  implements java.io.Serializable{
  private static final char RUBY_MAP[][] = {
    {'ぁ' , 'あ'} ,
    {'ぃ' , 'い'} ,
    {'ぅ' , 'う' , '\0' , 'ヴ'} ,
    {'ぇ' , 'え'} ,
    {'ぉ' , 'お'} ,

    {'\0' , 'か' , '\0' , 'が'} ,
    {'\0' , 'き' , '\0' , 'ぎ'} ,
    {'\0' , 'く' , '\0' , 'ぐ'} ,
    {'\0' , 'け' , '\0' , 'げ'} ,
    {'\0' , 'こ' , '\0' , 'ご'} ,

    {'\0' , 'さ' , '\0' , 'ざ'} ,
    {'\0' , 'し' , '\0' , 'じ'} ,
    {'\0' , 'す' , '\0' , 'ず'} ,
    {'\0' , 'せ' , '\0' , 'ぜ'} ,
    {'\0' , 'そ' , '\0' , 'ぞ'} ,

    {'\0' , 'た' , '\0' , 'だ'} ,
    {'\0' , 'ち' , '\0' , 'ぢ'} ,
    {'っ' , 'つ' , '\0' , 'づ'} ,
    {'\0' , 'て' , '\0' , 'で'} ,
    {'\0' , 'と' , '\0' , 'ど'} ,

    {'\0' , 'な'} ,
    {'\0' , 'に'} ,
    {'\0' , 'ぬ'} ,
    {'\0' , 'ね'} ,
    {'\0' , 'の'} ,

    {'\0' , 'は' , '\0' , 'ば' , 'ぱ'} ,
    {'\0' , 'ひ' , '\0' , 'び' , 'ぴ'} ,
    {'\0' , 'ふ' , '\0' , 'ぶ' , 'ぷ'} ,
    {'\0' , 'へ' , '\0' , 'べ' , 'ぺ'} ,
    {'\0' , 'ほ' , '\0' , 'ぼ' , 'ぽ'} ,

    {'\0' , 'ま'} ,
    {'\0' , 'み'} ,
    {'\0' , 'む'} ,
    {'\0' , 'め'} ,
    {'\0' , 'も'} ,

    {'ゃ' , 'や'} ,
    {} ,
    {'ゅ' , 'ゆ'} ,
    {} ,
    {'ょ' , 'よ'} ,

    {'\0' , 'ら'} ,
    {'\0' , 'り'} ,
    {'\0' , 'る'} ,
    {'\0' , 'れ'} ,
    {'\0' , 'ろ'} ,

    {'\0' , 'わ'} ,
    {} ,
    {} ,
    {} ,
    {'\0' , 'を'} ,

    {'\0' , 'ん'}
  };

  private String ruby;
  private String sort;

  public Ruby(){
  }
  public Ruby(String r){
    setRuby(r);
  }

  public String getRuby(){
    return ruby;
  }
  public String getSort(){
    return sort;
  }

  private static final char FIRST = ' ';
  public void setRuby(String r){
    ruby = r;

    StringBuffer sb = new StringBuffer();
    StringBuffer sbt = new StringBuffer();

    int before = -1;
    char bc = '';
    for(int i = 0; i < r.length(); i++){
      char c = r.charAt(i);

      int value = 0;
      int type = 0;

      if(c != 'ー'){
        boolean match = false;
        for(int v = 0; v < RUBY_MAP.length; v++){
          for(int t = 0; t < RUBY_MAP[v].length; t++){
            if(RUBY_MAP[v][t] == c){
              match = true;

              value = v;
              type = t;

              before = v;
              bc = c;
            }
          }
          if(match)
            break;
        }

        if(!match)
          throw new IllegalArgumentException(
            "文字 " + c + " は使用できません。");
      }else{
        if(before == -1)
          throw new IllegalArgumentException(
            "伸ばす音は先頭に配置できません。");

        if(bc == 'ん'){
          value = before;
          type = 1;
        }else{
          value = before % 5;
          type = 2;
        }
      }

      sb.append((char)(FIRST + value + 1));
      sbt.append((char)(FIRST + type + 1));
    }

    sb.append(FIRST);

    sb.append(sbt.toString());

    setSort(sb.toString());
  }
  private void setSort(String s){
    sort = s;
  }
}

// Title.java
package com.yamicha.namelist;

import javax.persistence.*;

@Embeddable public class Title
	implements java.io.Serializable{
	private String title;
	private Ruby ruby;

	public Title(){
		ruby = new Ruby();
	}
	public Title(String t , String r){
		this();
		title = t;
		ruby.setRuby(r);
	}
	public Title(String t , Ruby r){
		this();
		title = t;
		ruby = r;
	}

	public String getTitle(){
		return title;
	}
	@Embedded public Ruby getRuby(){
		return ruby;
	}

	public void setTitle(String t){
		title = t;
	}
	public void setRuby(Ruby r){
		ruby = r;
	}
}
 Person.javaはTitleを2つ持ちます。そうなるとカラム名がかぶって問題が生じそうですが、ここで用いるのが@AttributeOverride(s)です。これを使えばカラム名を任意のものに変更でき、しかもNested Embeddedにも対応しています。
// Person.java
package com.yamicha.namelist;

import javax.persistence.*;

@Entity @Table(name="namelist_person" , schema="yamicha")
	public class Person implements java.io.Serializable{
	private int id;
	private Category category;
	private Title fname;
	private Title lname;
	private String position;

	public Person(){
	}
	public Person(Title ln , Title fn , String p){
		this();
		lname = ln;
		fname = fn;
		position = p;
	}

	@Id @GeneratedValue @Column(name="id") public int getId(){
		return id;
	}
	@ManyToOne @JoinColumn(name="category" ,
		referencedColumnName="id")
		public Category getCategory(){
		return category;
	}
	@AttributeOverrides({
		@AttributeOverride(name="title" , 
			column=@Column(name="first_name")) ,
		@AttributeOverride(name="ruby.ruby" , 
			column=@Column(name="first_ruby")) ,
		@AttributeOverride(name="ruby.sort" , 
			column=@Column(name="first_sort"))})
		@Embedded public Title getFirstName(){
		return fname;
	}
	@AttributeOverrides({
		@AttributeOverride(name="title" , 
			column=@Column(name="last_name")) ,
		@AttributeOverride(name="ruby.ruby" , 
			column=@Column(name="last_ruby")) ,
		@AttributeOverride(name="ruby.sort" , 
			column=@Column(name="last_sort"))})
		@Embedded public Title getLastName(){
		return lname;
	}
	@Column(name="position") public String getPosition(){
		return position;
	}

	public void setId(int i){
		id = i;
	}
	public void setCategory(Category c){
		category = c;
	}
	public void setFirstName(Title t){
		fname = t;
	}
	public void setLastName(Title t){
		lname = t;
	}
	public void setPosition(String s){
		position = s;
	}
}

// Category.java
package com.yamicha.namelist;

import javax.persistence.*;
import java.util.*;

@Entity @Table(name="namelist_category" , schema="yamicha")
	public class Category implements java.io.Serializable{
	private int id;
	private String name;
	private List<Person> people;

	public Category(){
		people = new ArrayList<Person>();
	}
	public Category(String n){
		this();
		name = n;
	}

	@Id @GeneratedValue @Column(name="id") public int getId(){
		return id;
	}
	@Column(name="name") public String getName(){
		return name;
	}
	@OneToMany(mappedBy="category" , cascade=CascadeType.ALL)
		public List<Person> getPeople(){
		return people;
	}

	public void setId(int i){
		id = i;
	}
	public void setName(String n){
		name = n;
	}
	public void setPeople(List<Person> p){
		people = p;
	}

	public void link(){
		for(Person p : people)
			p.setCategory(this);
	}
}
 本当はCategory.peopleプロパティに@OrderByをつけてソートさせるつもりでしたが、単一のプロパティを用いてソートすることはできるものの、なぜか複数のプロパティを使ってソートしようとするとエラーになってしまい、断念しました。複数プロパティを使用するサンプルはJava EE 6のAPIリファレンスにも記載されており、仕様上は問題ないはずなのですが、非常に不可解です。EclipseLinkの問題でしょうか。
 仕方がないので、NameListAccess.javaでJPQLを使ってソートしています。
package com.yamicha.namelist;

import javax.ejb.*;
import javax.annotation.*;
import javax.persistence.*;
import java.util.List;
import java.util.ArrayList;

@Remote @Stateless(name="NameListAccess" ,
  mappedName="ejb/NameListAccess")
  public class NameListAccess{
  @PersistenceContext(unitName="MySQL") private EntityManager em;

  public void regist(){
    em.createQuery("DELETE FROM Person p").executeUpdate();
    em.createQuery("DELETE FROM Category c").executeUpdate();

    Category pm = new Category("日本の総理大臣");
    pm.getPeople().add(new Person(new Title("村山" , "むらやま") ,
      new Title("富市" , "とみいち") , "内閣総理大臣(52人目)"));
    pm.getPeople().add(new Person(new Title("橋本" , "はしもと") ,
      new Title("龍太郎" , "りゅうたろう") , "内閣総理大臣(53人目)"));
    pm.getPeople().add(new Person(new Title("小渕" , "おぶち") ,
      new Title("恵三" , "けいぞう") , "内閣総理大臣(54人目)"));
    pm.getPeople().add(new Person(new Title("森" , "もり") ,
      new Title("喜朗" , "よしろう") , "内閣総理大臣(55人目)"));
    pm.getPeople().add(new Person(new Title("小泉" , "こいずみ") ,
      new Title("純一郎" , "じゅんいちろう") , "内閣総理大臣(56人目)"));
    pm.getPeople().add(new Person(new Title("安倍" , "あべ") ,
      new Title("晋三" , "しんぞう") , "内閣総理大臣(57人目)"));
    pm.getPeople().add(new Person(new Title("福田" , "ふくだ") ,
      new Title("康夫" , "やすお") , "内閣総理大臣(58人目)"));
    pm.getPeople().add(new Person(new Title("麻生" , "あそう") ,
      new Title("太郎" , "たろう") , "内閣総理大臣(59人目)"));
    pm.getPeople().add(new Person(new Title("鳩山" , "はとやま") ,
      new Title("由紀夫" , "ゆきお") , "内閣総理大臣(60人目)"));
    pm.getPeople().add(new Person(new Title("菅" , "かん") ,
      new Title("直人" , "なおと") , "内閣総理大臣(61人目)"));
    pm.link();
    em.persist(pm);

    Category y = new Category("日本円紙幣の肖像");
    y.getPeople().add(new Person(new Title("夏目" , "なつめ") ,
      new Title("漱石" , "そうせき") , "千円札D"));
    y.getPeople().add(new Person(new Title("野口" , "のぐち") ,
      new Title("英世" , "ひでよ") , "千円札E"));
    y.getPeople().add(new Person(new Title("新渡戸" , "にとべ") ,
      new Title("稲造" , "いなぞう") , "五千円札D"));
    y.getPeople().add(new Person(new Title("樋口" , "ひぐち") ,
      new Title("一葉" , "いちよう") , "五千円札E"));
    y.getPeople().add(new Person(new Title("福沢" , "ふくざわ") ,
      new Title("諭吉" , "ゆきち") , "一万円札D,E"));
    y.link();
    em.persist(y);
  }

  public List<Category> getCategories(){
    return em.createQuery(
      "SELECT c FROM Category c" , Category.class).getResultList();
  }
  public List<Person> getPeople(Category c){
    TypedQuery<Person> tq = em.createQuery(
      "SELECT p FROM Category c JOIN c.people p WHERE c.id = ?1 " +
      "ORDER BY p.lastName.ruby.sort , p.lastName.title , " +
      "p.firstName.ruby.sort , p.firstName.title" ,
      Person.class);
    tq.setParameter(1 , c.getId());
    return tq.getResultList();
  }
}
 NameListServlet.javaでサンプルを登録・表示します。
package com.yamicha.namelist;

import javax.servlet.annotation.*;
import javax.ejb.*;
import javax.annotation.*;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.persistence.*;
import java.io.*;
import java.util.List;
import java.util.ArrayList;

@WebServlet(name="namelistservlet" , urlPatterns={"/*"})
  public class NameListServlet extends HttpServlet{
  @EJB(beanName="NameListAccess") private NameListAccess na;

  public void doPost(HttpServletRequest request ,
    HttpServletResponse response) throws IOException{
    doGet(request , response);
  }
  public void doGet(HttpServletRequest request ,
    HttpServletResponse response) throws IOException{
    na.regist();

    request.setCharacterEncoding("UTF-8");
    response.setHeader("Content-type" , "text/html;charset=UTF-8");
    PrintWriter out = response.getWriter();

    out.println("<html>");
    out.println("<head>");
    out.println("<title>Name List</title>");
    out.println("</head>");
    out.println("<body>");

    out.println("<b>Name List</b><br /><br />");

    List<Category> categories = na.getCategories();
    for(Category category : categories){
      out.println("<b>" + category.getName() + "</b>");
      out.println("<ul>");
      List<Person> people = na.getPeople(category);
      for(Person person : people){
        out.println("<li>");
        out.println("<b>" + person.getLastName().getTitle() + " " +
          person.getFirstName().getTitle() + "</b>");
        out.println("<small>(" +
          person.getLastName().getRuby().getRuby() + " " +
          person.getFirstName().getRuby().getRuby() + ")</small>");
        out.println(" - " + person.getPosition());
        out.println("</li>");
      }
      out.println("</ul>");
    }

    out.println("</body>");
    out.println("</html>");

    out.close();
  }
}
 このプログラムを動かしてみるまで気づきませんでしたが、総理大臣はそれなりに名前が分散しているのに比べ、紙幣の文化人は出席番号が後ろの方になりそうな人ばかりなのはなぜなのでしょうか。
カテゴリ [開発魔法][社会問題][経済・知的財産] [トラックバック 0][コメント 0]

消費税増税の先陣争い
2010/06/20(Sun)22:41:22
 自民党が消費税10%案を公約に明記し、民主党も消費税増税を公約に明記しました。税率については、菅氏は「自民党が提案している10%という数字を一つの参考にさせていただきたい」と述べており、おおむね自民党案と類似したものになることが予想されます。一方、党内や他の野党からは批判の声も出ており、自民党からは「民主党の公約は自民党のコピー」との声も聞かれます。
 民主党が自民党の後を追うように消費税案を設定したのは、ある程度仕方のないところでしょう。与党が消費税増税を主張するのは非常に難しく、下手に言い出そうものなら野党に攻め立てられて支持を失う恐れがあるため、野党がまず言い出さなければ議論にならない現状があります。消費税はこれまで非常に嫌われてきており、さらに野党時代の民主党が年金の財源として消費税増税を主張した際には、自民党が論点をかき乱してしまい、結局消費税議論はほとんど行われてきませんでしたが、今回の参院選では自民党はむしろ民主党との差別化のために消費税増税を主張しており、民主党もそれを受けて公約を設定したため、ここでようやく消費税増税を論じた選挙が行われそうです。
 現在の財政状況からして、望む望まざるにかかわらず消費税増税はいずれ避けようがなく、そのような意味では議論が深まるのは歓迎すべきことです。参院選終了後は最長で3年ほど選挙のない期間が続きますが、もし今回の参院選で消費税議論がなされなければ、最長3年にわたって消費税問題で大混乱を起こす可能性が考えられますので、このタイミングで二大政党がともに消費税を持ち出したのは、無難なものであるといえます。
 しかし、ここで重要になるのが消費税の使い道です。消費税は逆進性が強い税であるため、逆進性を抑えるには使い道を考える必要があります。例えば、消費税で確保した財源を福祉に充当すれば逆進性を緩和できますが、これを使って相続税を減免などすれば逆進性は緩和されません。逆進性を打ち消せない用途に財源を回したいのであれば、それは消費税増税によって捻出すべきではありません。
 中でも気になるのが法人税減税論です。法人税を減税すれば、その分が雇用や設備投資、給与に回って経済が回転し、国際競争力も高まるというのが減税の理屈ですが、これへの財源として消費税を充てることには慎重であるべきです。福祉財源の欠乏と消費税の逆進性を考慮すれば、福祉目的の消費税増税に比べて法人税減税目的の消費税増税が受け入れられにくいのは明白です。
 無論、本当に雇用や設備投資が回復し、経済の回転が見込めるのであれば、法人税減税も方法の1つとして検討されるべきです。しかし、大企業が未曾有の利益を出した際に日本で何が起こっていたかを考えれば、安易な減税が景気を刺激するかは非常に疑問と言わざるを得ません。その際には企業のパイが増えたはずですが、実際には派遣の使い捨てや偽装請負、下請けの締め付け、その他様々な問題が発生し、「実感なき景気回復」と揶揄される有様でした。せっかく国民全員に逆進的に負担をかけて法人税を減税したはずが、これの二の舞になっては困るのです。法人税を減税するために国民に負担を要求したければ、最低限これを防止する策を実現してからでなくてはいけません。
 また、消費税増税を公約に盛り込むのであれば、民主党は年金制度改革案も主要政策として堂々と訴えるべきでしょう。民主党がかねてから主張している全額税方式は、逆進性が極めて強い年金保険料と不公平かつ矛盾に満ちた第三号問題を解消できる優れた方法ですが、これを行うかどうかで消費税率の見方が変わってきます。福田内閣時に与党側が躍起になって全額税方式を否定しようとしたと推測される「社会保障国民会議」の試算ですら、事実上3%の消費税増税で全額税方式は可能とされていますが、それなら実質的に民主党の消費税10%は自民党の7%に相当します。この通り、消費税率の意味合いが全く変わってくる以上、民主党は年金制度改革案も同時に訴える必要があります。
 なぜ消費税増税がここまで国民に嫌われるかといえば、逆進性が強いとみなされているためです。そして、消費税で福祉などの社会保障を強化すれば、弱者ほど恩恵を受けるため累進的となり、本来なら歓迎されるはずのところを、なぜ逆進性が強いとみなされるかといえば、消費税が福祉以外に無駄遣いされる懸念を多数の国民が抱いているためです。すなわち、「消費税アレルギー」は政治への不信感に起因している部分が大きいといえます。
 また、今回の消費税議論は新聞などで一定の評価を受けていますが、消費税増税はそれを財源として有効な政策を実現して初めて意味があるのであって、消費税を上げること自体が評価に値するわけではありません。それを履き違え、やれ我々が先に増税を言い出した、ライバル政党の優位性を封じるためにこちらも消費税を持ち出した、などという争いを続けている限り、単に「消費税上げない論争」が「消費税増税論争」に切り替わっただけで、意味がありません。これでは消費税の使途に不安を抱かれるのも無理はありません。

 このほど、これまで何をしても動作しなかったParrot + Rakudo for Win32がようやく動作したため、ここに覚え書きをしたためておきます。
 Parrotはもともとエイプリルフールのネタから生まれたソフトウェアで、PerlやPython、その他様々なスクリプト言語を動かせるランタイムという触れ込みで開発されています。Rakudo Perlはこれの上で動作するPerl 6の実装です。
 ところが、このParrotやRakudo、実際には前代未聞の出る出る詐欺に陥っています。Perl 6が近いうちに出ると発表された際には、開発者の間には少なからず盛り上がりが見られ、今のPerl 5もいずれは6に移行するからPerl 6を習得すべしとの機運もありましたが、これがすでに何年も前の話です。途中でPugsなどの玩具的な実装は出たものの、待てど暮らせどまともなPerl 6が出る気配はなく、最近ようやくRakudo Perlがベータ程度に実装されてきている状態です。ParrotとRakudoは複数のプラットフォーム向けにリリースされています。
 肝心のインストール方法ですが、まずParrotをインストールし、それからRakudoを同じディレクトリにインストールします。同じディレクトリにインストールするものであるはずなのに、Rakudoのインストール時に警告を出してくるのが何とも意地悪です。ParrotとRakudoのバージョンは合わせなくてはならないとサイトにも書いてありますので、その通りにしておきます。
 また、インストールの際にはインストールディレクトリ名には手をつけない方が無難なようです(ドライブ名は変えてもよい)。これまで散々動作に失敗してきたのは、デフォルトではParrot-2.5.0などとバージョン名がついているところを、運用しやすくするために単にParrotと変更していたのが原因でした。それにしても、なぜインストーラにインストール先ディレクトリ変更機能がついているのでしょうか
 インストールが終了すると、自動的にParrotのbinディレクトリが環境変数PATHに追加されます。ちなみに、これはアンインストールしても除去されないため、アンインストールの際には手作業で取り除かなくてはなりません。前のバージョンを消して新しいバージョンを入れたりする際には面倒そうです。
 ひとまず、ドキュメントにしたがって次のようなファイルを作り(ファイルの最後に必ず空行を入れること。拡張子は.pasmでなければならない。pasmはおそらくParrotのアセンブリの意)、
say "It's Parrot!"
end

 コマンドプロンプトから次のように打ってみて、
parrot (ファイル名)
 動作したらParrotの導入は成功です。
 RakudoはParrotとは別物ですから、こちらもテストしてみる必要があります。かつて実際に、Parrotは普通に動くのに、Perl6は何をしても動作せず、泣きを見たことがあります。
 とはいえ、こちらは単に
perl6
 と打てば対話モードになりますので、後はPerl 6の世界を満喫するだけです。十分に満喫したら、「exit」で我に返りましょう。
Path> perl6
> "It's Perl6!".say();
It's Perl6!
> loop (my $i = 10; $i < 13; $i++) {$i.say();}
10
11
12
> "It's Perl6!".say();
It's Perl6!
> my @arr = (1 , 2 , 3); for(@arr) {$_.say();}
1
2
3
> loop (my $i = 10; $i < 13; $i++) {($i * $i).say();}
100
121
144
> exit
 ここからは自由にParrotやRakudoを使用するだけです。ひとまず簡素なCGIを書いてみるのも面白いのではないでしょうか。
#!/parrot-2.5.0/bin/parrot -a

say "Content-type: text/plain\n"
say "Hello Parrot."
say "You can speak various languages."
end

 オプション「-a」をつけておくと、.pasm以外のファイルでもpasmとみなして解釈してくれます。
 perl6も使用してみます。
#!/parrot-2.5.0/bin/perl6

"Content-type: text/plain\n".say();
"Hello Rakudo Perl.".say();
 エラー時の挙動など、実用に耐えるかはともかくとして、とりあえず動くようです。
カテゴリ [開発魔法][社会問題][経済・知的財産] [トラックバック 0][コメント 0]

口を出せねば・・・?
2010/02/27(Sat)23:24:42
 企業献金を禁止する法改正を待つまでもなく、経団連が企業献金への関与を中止する方針を固めました。今までの経団連は「金も出すが口も出す」方針で献金のあっせんを行っていましたが、民主党の大勝によって政治関与が難しくなった上、政治資金に対する国民からの視線も厳しくなる一方ですので、中止を決断したものとみられます。
 そもそも民主党が掲げている企業献金禁止案自体、自民党への兵糧攻めの意味合いが強いとみなされていますが、今回の決定はそれが前倒し実行されるようなものですから、与党時代に財界との蜜月関係を築き、大量の献金を確保してきた自民党にとっては、大打撃となるであろうことは想像に難くありません。その上に「郵政選挙」の大量当選から状況が一変し、政党交付金も大幅に減額されるため、なおさらダメージは大きくなります。ただでさえ弱り目の自民党としては、まさに踏んだり蹴ったりの状況です。
 しかし、自民党はこれを危機的状況であると認識し、下手に自分の手足を縛るより、むしろ財界依存を打破するチャンスであると捉え直すべきでしょう。自民党は長らく与党の利権に支えられて権威を誇ってきた政党ですので、下野した途端に混乱に陥るのは当然とさえいえますし、政権交代が日常的に発生する二大政党制に対応するためには体質改善が必要ですが、本件もその一環に過ぎません。
 二大政党制においては、両者の立場に差異が少ない中で、それぞれが党の個性を発揮することが重要になりますが、それでは「自民党らしさ」とは一体何なのでしょうか。自民党は「保守」を強調していますが、保守とは何なのでしょうか。財界の傀儡となり、大量の企業献金を受け取る見返りとして、日本のためにならない政策でも二つ返事で実行することが、「自民党らしさ」や「保守」なのでしょうか。そうでないならば、企業献金がいかに「自民党らしさ」を阻害してきたか分かろうというものです。
 今後、企業献金への制限が厳しくなることはあれ、緩和される可能性は低いでしょう。企業献金に対する国民の目も同様です。まして、自民党は経団連ら財界の言い分を二つ返事で受け入れてきており、大企業のためにはなっても日本の国益を損ねる政策を実行したり、あるいは実行しようとした結果が、今回の大敗北の直接の原因となっています。政治資金規正の意味でも、また「自民党らしさ」を発揮する意味でも、企業献金依存から脱却しなくてはならないのは明らかで、これを機に党内の改革を進める必要があります。
 ただ、自民党がそのような改革を行う上で、不安なのが総務会長の田野氏のような考え方です。曰く、「野党だから要望を政策に反映できない中で、経団連の決定はある程度仕方ない」というのです。すなわち、与党に舞い戻ったら財界の要望を次々に政策に反映し、再び大量の献金を受け取ろうという意味であるとみなせます。政権交代のある政治においては、国民を無視して財界の傀儡となっていては選挙に勝てませんが、氏はなぜ自民党が敗北に至ったか分かっているのでしょうか。
 経団連は献金で自民党を買収し、自分の利益にはなっても国益に反する政策を大量に実行させた結果、企業の集合体でありながら国民からの信頼を失い、自民党を通して退場勧告を突きつけられました。経団連が大企業の取りまとめ役として今後も力を発揮したいのであれば、経団連は体質を変える必要があり、新会長の米倉氏はそれを行わなくてはなりません。そして、もし経団連が変わるのであれば、自民党も変わらなくてはなりません。仮に経団連が変わらず、自民党もまた変わらなければ、国民から再び不信任を突きつけられる結果が待っています。
 現状の自民党は「敵失」に期待するしかない状況に置かれていますが、その敵失が民主党にダメージを与えることはあっても、自民党の信頼回復にはほとんど役立っておらず、支持を回復するのは困難な状況です。だからこそ、自民党は経団連の決定を逆に生かし、献金によるがんじがらめの状態から脱却し、「自民党らしさ」を発揮する準備を整えるべきでしょう。そのような努力と改革を重ねていけば、低IQ選挙のような一過性のものに頼らなくても、いずれ必ず信頼を得られるに違いありません。

 JSFにおけるf:selectItemsには、ManagedBeanのコレクション(例えばMap)を指定できました。すなわち、ManagedBeanでの操作次第でメニューの中身を変更できることを意味しますが、これとAjaxを組み合わせると便利ではないでしょうか。すなわち、何らかのイベントにあわせてAjaxリクエストを送信し、そこでコレクションの中身を変更するのと同時に、f:selectItemsを使用するコントロールをf:ajaxのrenderに指定しておいて再読み込みさせれば、任意のタイミングで手軽にドロップダウンメニューなりラジオボタンなりの中身を変更できそうです。
 すなわち、これまでは主に結果表示に使っていたAjaxを、今度はコントロールの動的な変更に使用してみようという試みです。単にメニューの中身を変えるだけならAjaxなしのJavaScriptでもできますが、あらゆるデータをJavaScript中にいちいち全部記述していると非常に膨大になる可能性がある場合、あるいは内容を動的に更新したい場合には、Ajaxの方が便利でしょう。
 せっかくAjaxでメニューを動的に変更するのですから、今回はメニュー項目をEntityとしました。
/WEB-INF
 /classees
  /com
   /yamicha
    /varmenu
     @Entity Account.java
     @Entity AccountType.java
     @Entity Journal.java
     @ManagedBean AccountBean.java
     @Stateless AccountAccess.java
  /META-INF
   persistence.xml
 web.xml
account.xhtml
 web.xmlは完全に定型文状態です。
<?xml version="1.0" encoding="ISO-8859-1"?>

<web-app>
  <context-param>
    <param-name>javax.faces.PROJECT_STAGE</param-name>
    <param-value>Development</param-value>
  </context-param>

  <display-name>JSF 2.0 Account Servlet</display-name>
  <description>JSF 2.0 Account Sample Servlet</description>

  <servlet>
    <servlet-name>jsf20account</servlet-name>
    <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
  </servlet>

  <servlet-mapping>
    <servlet-name>jsf20account</servlet-name>
    <url-pattern>*.jsf</url-pattern>
  </servlet-mapping>
</web-app>
 application.xmlも同様です。
<?xml version="1.0" encoding="UTF-8"?>

<persistence version="1.0" xmlns="http://java.sun.com/xml/ns/persistence">
  <persistence-unit name="MySQL" transaction-type="JTA">
    <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
    <jta-data-source>jdbc/MySQL</jta-data-source>
    <properties>
      <property name="eclipselink.jdbc.driver"
        value="com.mysql.jdbc.Driver" />
      <property name="eclipselink.ddl-generation"
        value="create-tables" />
      <property name="eclipselink.ddl-generation.output-mode"
        value="database" />
      <property name="eclipselink.target-database" value="MySQL" />
      <property name="eclipselink.logging.level" value="FINE"/>
    </properties>
  </persistence-unit>
</persistence>
 @Entityクラスとしては、勘定科目の種別(資本、負債など)を記録するAccountType、勘定科目(現金、当座預金など)を記録するAccount、取引を記録するJournalの3つを作成しました。本来、Journalには取引の日付や小書きなどのデータも格納できるようにすべきですし、そもそも複式の記帳としては貸借がセットになっていなければおかしいのですが、今回はあくまでAjaxのコードですから、「金額」のみを持つ簡単なものとしました。
 まずAccountTypeの内容をドロップダウンリストに表示し、ユーザーがいずれかの項目を選択すると、そのAccountTypeに属するAccountが次のドロップダウンリストに表示される、というUIを想定して作成しています。その上で、金額を入力して送信するとJournalに記録されるものとします。
// AccountType.java
package com.yamicha.varmenu;

import javax.persistence.*;
import java.util.*;

@Entity @Table(name="varmenu_account_type" , schema="yamicha")
	public class AccountType implements java.io.Serializable{
	private int id;
	private String name;
	private List<Account> accounts;

	public AccountType(){
		accounts = new ArrayList<Account>();
	}
	public AccountType(String s){
		this();
		name = s;
	}

	@Id @GeneratedValue @Column(name="id") public int getId(){
		return id;
	}
	@Column(name="name") public String getName(){
		return name;
	}
	@OneToMany(cascade=CascadeType.ALL , mappedBy="type")
		public List<Account> getAccounts(){
		return accounts;
	}

	public void setId(int i){
		id = i;
	}
	public void setName(String s){
		name = s;
	}
	public void setAccounts(List<Account> a){
		accounts = a;
	}

	public void link(){
		for(Account a : accounts)
			a.setType(this);
	}
}

// Account.java
package com.yamicha.varmenu;

import javax.persistence.*;
import java.util.*;

@Entity @Table(name="varmenu_account" , schema="yamicha")
	public class Account implements java.io.Serializable{
	private int id;
	private String name;
	private int price;
	private AccountType type;
	private List<Journal> journals;

	public Account(){
		journals = new ArrayList<Journal>();
	}
	public Account(String s){
		this();
		name = s;
	}

	@Id @Column(name="id") @GeneratedValue public int getId(){
		return id;
	}
	@Column(name="name") public String getName(){
		return name;
	}
	@ManyToOne @JoinColumn(name="type") public AccountType getType(){
		return type;
	}
	@OneToMany(cascade=CascadeType.ALL , mappedBy="account")
		public List<Journal> getJournals(){
		return journals;
	}

	public void setId(int i){
		id = i;
	}
	public void setName(String s){
		name = s;
	}
	public void setType(AccountType t){
		type = t;
	}
	public void setJournals(List<Journal> j){
		journals = j;
	}
}

// Journal.java
package com.yamicha.varmenu;

import javax.persistence.*;

@Entity @Table(name="varmenu_journal" , schema="yamicha")
	public class Journal implements java.io.Serializable{
	private int id;
	private int price;
	private Account account;

	public Journal(){
	}
	public Journal(int p){
		price = p;
	}

	@Id @Column(name="id") @GeneratedValue public int getId(){
		return id;
	}
	// 帳簿の金額に price というプロパティ名は奇妙ながら
	// value などでは色々面倒なので...
	@Column(name="price") public int getPrice(){
		return price;
	}
	@ManyToOne @JoinColumn(name="account") public Account getAccount(){
		return account;
	}

	public void setId(int i){
		id = i;
	}
	public void setPrice(int p){
		price = p;
	}
	public void setAccount(Account a){
		account = a;
	}
}
 これらのEntityはAccountAccessクラスから使用します。
package com.yamicha.varmenu;

import javax.ejb.*;
import javax.annotation.*;
import javax.persistence.*;
import java.util.List;
import java.util.ArrayList;

@Remote @Stateless(name="AjaxAccountAccess" ,
	mappedName="ejb/AjaxAccountAccess")
	public class AccountAccess{
	@PersistenceContext(unitName="MySQL") private EntityManager em;

	// サンプルデータ登録用メソッド
	public void regist(){
		AccountType assets = new AccountType("資産");
		AccountType liabilities = new AccountType("負債");
		AccountType equity = new AccountType("資本");
		AccountType income = new AccountType("収益");
		AccountType expenses = new AccountType("費用");

		assets.getAccounts().add(new Account("現金"));
		assets.getAccounts().add(new Account("当座預金"));
		assets.getAccounts().add(new Account("売掛金"));
		assets.getAccounts().add(new Account("のれん"));
		assets.getAccounts().add(new Account("開発費"));
		assets.link();
		em.persist(assets);

		liabilities.getAccounts().add(new Account("買掛金"));
		liabilities.getAccounts().add(new Account("支払手形"));
		liabilities.getAccounts().add(new Account("社債"));
		liabilities.link();
		em.persist(liabilities);

		equity.getAccounts().add(new Account("資本金"));
		equity.getAccounts().add(new Account("資本準備金"));
		equity.link();
		em.persist(equity);

		income.getAccounts().add(new Account("売上"));
		income.getAccounts().add(new Account("受取手数料"));
		income.getAccounts().add(new Account("仕入割引"));
		income.link();
		em.persist(income);

		expenses.getAccounts().add(new Account("仕入"));
		expenses.getAccounts().add(new Account("除却損"));
		expenses.getAccounts().add(new Account("貸倒損失"));
		expenses.link();
		em.persist(expenses);

		em.flush();
	}

	public List<AccountType> getAccountTypes(){
		return (List<AccountType>)em.createQuery(
			"SELECT t FROM AccountType t").getResultList();
	}
	public List<Account> getAccounts(AccountType t){
		em.merge(t);
		return new ArrayList<Account>(t.getAccounts());
	}
	public List<Journal> getJournals(){
		return (List<Journal>)em.createQuery(
			"SELECT j FROM Journal j ORDER BY j.id DESC"
			).getResultList();
	}

	public AccountType getAccountType(int id){
		return em.find(AccountType.class , id);
	}
	public Account getAccount(int id){
		return em.find(Account.class , id);
	}

	public void addJournal(Journal j , int acc_id){
		Account a = em.getReference(Account.class , acc_id);
		j.setAccount(a);
		em.persist(j);
	}
}
 AccountAccessはAccountBeanクラスで使用します。
package com.yamicha.varmenu;

import javax.ejb.*;
import javax.annotation.*;
import javax.faces.validator.ValidatorException;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.application.FacesMessage;
import javax.faces.bean.*;
import javax.faces.event.*;
import java.util.*;

@ManagedBean @ViewScoped public class AccountBean{
	@EJB(beanName="AjaxAccountAccess") private AccountAccess aa;
	private Map<String , Integer> accountTypes;
	private int accountType;
	private Map<String , Integer> accounts;
	private int account;
	private int price;

	public AccountBean(){
		accountTypes = new TreeMap<String , Integer>();
		accounts = new TreeMap<String , Integer>();

		accountType = -1;
		account = -1;

		price = 0;
	}

	// DI 後でなければドロップダウン用の Map を作成できないので
	// Map へのデータ登録は @PostConstruct で行う
	@PostConstruct private void init(){
		createAccountTypes();
		createAccounts(-1);
	}

	private void createAccountTypes(){
		accountTypes.clear();

		accountTypes.put("種別を選択" , -1);
		for(AccountType t : aa.getAccountTypes())
			accountTypes.put(t.getName() , t.getId());

		accountType = -1;
	}
	private void createAccounts(int id){
		accounts.clear();

		accounts.put("勘定を選択" , -1);
		if(id != -1){
			AccountType at = aa.getAccountType(id);
			if(at != null){
				for(Account a : aa.getAccounts(at)){
					accounts.put(
						a.getName() , a.getId());
				}
			}
		}

		account = -1;
	}

	// サンプルデータ登録用メソッド
	public void regist(){
		aa.regist();
		init();
	}

	// AccountType のドロップダウンの選択項目が
	// 変更された際に呼び出されるイベント
	// AccountType に対応する Account をデータベースから
	// 取得し、Account のドロップダウンの Map に登録する
	public void changeAccountType(ValueChangeEvent e){
		createAccounts(((Integer)e.getNewValue()).intValue());
	}

	public void addJournal(){
		aa.addJournal(new Journal(price) , account);
		price = 0;
		init();
	}

	public int getAccountType(){
		return accountType;
	}
	public Map<String , Integer> getAccountTypes(){
		return accountTypes;
	}
	public int getAccount(){
		return account;
	}
	public Map<String , Integer> getAccounts(){
		return accounts;
	}
	public int getPrice(){
		return price;
	}
	public List<Journal> getJournals(){
		return aa.getJournals();
	}

	public void setAccountType(int a){
		accountType = a;
	}
	public void setAccountTypes(Map<String , Integer> a){
		accountTypes = a;
	}
	public void setAccount(int a){
		account = a;
	}
	public void setAccounts(Map<String , Integer> a){
		accounts = a;
	}
	public void setPrice(int p){
		price = p;
	}

	// 勘定科目が選択されていない場合に
	// エラーを発生させるバリデータ
	public void accountValidator(FacesContext context ,
		UIComponent component , Object value){
		if(((Integer)value) == -1){
			throw new ValidatorException(
				new FacesMessage("勘定を選択してください。"));
		}
	}
}
 JSF + EJB + JPAは中身の割にコードが長くなるので困りますが、以上でJavaコードは終わり、ようやくxhtmlです。
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
  xmlns:h="http://java.sun.com/jsf/html"
  xmlns:f="http://java.sun.com/jsf/core"
  xmlns:c="http://java.sun.com/jsp/jstl/core"
  xmlns:ui="http://java.sun.com/jsf/facelets">

<h:head>
  <title>JSF 2.0 Variable Dropdown</title>
</h:head>

<h:body>
  <b>JSF 2.0 Variable Dropdown</b>

  <h:form>
    <h:panelGrid columns="2">
      <h:outputText value="AccountType:" />
      <h:selectOneMenu value="#{accountBean.accountType}"
        valueChangeListener="#{accountBean.changeAccountType}">
        <f:selectItems value="#{accountBean.accountTypes}" />
        <f:ajax execute="@this" render="account_list" />
      </h:selectOneMenu>

      <h:outputText value="Account:" />
      <h:selectOneMenu id="account_list" value="#{accountBean.account}"
        validator="#{accountBean.accountValidator}">
        <f:selectItems value="#{accountBean.accounts}" />
      </h:selectOneMenu>

      <h:outputText value="Value:" />
      <h:inputText value="#{accountBean.price}" />
    </h:panelGrid>

    <h:commandButton value="Add" action="#{accountBean.addJournal}" />

    <hr />
  </h:form>

  <table border="1">
    <tr>
      <td>Type</td>
      <td>Account</td>
      <td>Price</td>
    </tr>

    <ui:repeat value="#{accountBean.journals}" var="j" end="20">
      <tr>
        <td><h:outputText value="#{j.account.type.name}" /></td>
        <td><h:outputText value="#{j.account.name}" /></td>
        <td><h:outputText value="#{j.price}" /></td>
      </tr>
    </ui:repeat>
  </table>

  <h:form>
    <h:commandButton value="Regist Sample Accounts"
      action="#{accountBean.regist}" />
  </h:form>

</h:body>

</html>
 最初に「Regist Sample Accounts」を押すとサンプルの勘定科目が登録され、その後はAccountTypeドロップダウンに選択肢が現れます。ここから適当な勘定の種類(例えば「資産」)を選択すると、下のAccountドロップダウンに選択肢が現れます(「資産」を選んだ場合であれば、「のれん」「売掛金」「当座預金」「現金」「開発費」。開発費は費用ではなく繰延資産です。念のため)。後はその下のValueテキストボックスに金額を入れて「Add」を押せば、取引のデータが登録されます。また、Accountドロップダウンの項目を選択せずに「Add」を押すと、バリデータによってエラーメッセージが表示されます。
 データベースのせいで複雑になってはいますが、つまりは単にexecuteで必要なデータを送信し、Mapの中身を変更し、renderで再描画するだけですから、この手法は手軽な割に便利そうです。
カテゴリ [開発魔法][社会問題][経済・知的財産] [トラックバック 0][コメント 0]

経済旧体連合会
2010/01/25(Mon)01:25:26
 経団連の次期会長として、住友化学の米倉氏を当てる人事が固まりました。財閥系企業出身者の会長就任は今回が初めてです。氏は2004年から4年に渡って経団連副会長、その後は評議員会の議長のポストに就いており、その手腕が高く評価されたものとみられます。また、氏には石油事業の海外展開に道筋をつけたなどの功績がある他、マラリア被害がひどいアフリカで用いる蚊帳を開発し、現地生産を成功させるといった活躍もあるようです。このまま人事が確定すれば、5月にも正式に就任することとなります。
 かねてから経団連は自民党に相当な比重を置いており、毎年の政策評価や献金額でも自民党が民主党を大幅に上回っていました。特に政策評価には明らかに恣意的にしか見えない部分も散見される有様で、実際に民主党が躍進した2009年には政策評価を見送らざるを得ませんでした。もし経団連が公平・公正に政策評価を行っていたか、少なくともその自負があるのなら、政権交代の可能性など無関係に政策評価を行ったとしても、何の問題もなかったはずです。これでは民主党政権下で経団連の影響力が地に落ちるのも当然というもので、「財閥系」の不文律を破っての会長就任となる米倉氏には、民主党との関係を充実させる役目も期待されているようです。
 しかしながら、経団連会長がまず取り組まなくてはならない難題は、国民からの信頼を回復することに他なりません。かつての与党である自民党と蜜月関係にあった経団連は、自民党に様々な政策を実現させてきましたが、それが自民党の敗因の1つとなったことは明らかです。ある意味、国民が直接投票可能な自民党を通し、経団連に退場勧告を突きつけたようなものと言っても過言ではありません。
 政権交代のある政治においては、相手が民主党どころか自民党であっても、これまでのように二つ返事で経団連の傍若無人な振る舞いを受け入れてくれるわけがありませんし、実際に受け入れれば選挙で敗北するのみです。そのような意味でも、経団連の発言力は著しく低下しているといえるでしょう。
 この状況を打破するには、経団連はまず国民の信頼を勝ち取らなくてはなりません。しかし、今まで経団連がやってきたことを考えると、それは非常に険しい道といえるでしょう。例えば、談合の課徴金引き上げの際には、当初提示されていた「欧米並み」の水準に文句をつけ、小幅の引き上げにとどめてしまいました。談合は要するに税金の横領に当たるわけですから、自己利益のために税金横領の罰則を引き下げたと非難されても仕方がありません。また、ミートホープや三菱自動車問題など生命や食品にかかわる複数の事件は、公益通報がなければ闇に葬られていた可能性がありますが、経団連は公益通報者保護法の適用基準を厳格に修正させてしまいました。自分の利益のためであれば、国民の生命や健康を犠牲にすることもいとわないようです。
 経済政策の面でも、以前の会長であった奥田氏(トヨタ)は「消費税を毎年1%ずつ上げ、法人税は下げる」という内容の「奥田ビジョン」を発表していますし、その次の会長である御手洗氏(キヤノン)の時期には無賃残業合法化を積極的に推進し、政府案では年収900万円以上を基準としていたところを、経団連は400万円にすべきと主張し、インターネット上ではごく小規模ながらもキヤノン製品不買の動きさえ見られました。本来なら信用第一のはずの企業の集合体でありながら、信用は完全に地に落ちていると考えて間違いないでしょう。
 無論、これまでの経団連の意義を全否定するつもりはありません。今後どうなるかは不明ではあるものの、少なくとも今までの経団連は「大企業の、大企業による、大企業のための組織」に過ぎず、決して日本や国民の利益など考えてはいませんでしたが、たまたま「経団連が望む政策」と「日本に必要な政策」が合致した場合の政策実現に関しては、経団連にも功績があるといえるでしょう。
 ところが、最近では野放図な規制緩和による弊害が次々と表に出てきており、世界同時不況もそれに拍車をかけている状況です。緩和すべき無用な規制が多く存在していた時代には、経団連もそれなりに活躍できていたはずですが、最近では「経団連が望む政策」と「日本に必要な政策」が完全に乖離・対立してしまっています。
 そして、経団連が自己利益至上主義の主張を行っている限り、国民からの信頼は決して回復しません。経団連は自ら「企業が海外に逃げる」と主張している通り、日本が荒廃したとしても海外に脱出すれば済むことですから、日本を壊滅させてでも自分の利益を最大化しようとするのは理にかなった行動ではありますが、前述の通りもはやそれは通用しないと知るべきでしょう。
 かつて鳩山氏は所信表明演説にて、自民・公明体制を「経済の合理性に偏った政治」であると批判していましたが、自公政治全体への評価はともかくとして、経団連の政策を実現してきたという意味で言えば、これは正しくありません。少なくとも今までの経団連は「自分の利益を最大化する」ことを至上命題としており、日本経済を省みてはきませんでした。経団連に参加している大企業に利益を与えつつ、経済の合理性に反する政策というのは十分に存在し得ます。例えば、無用な規制緩和によって大企業が利益を得たとしても、それが国民や日本経済にダメージを与えれば、それは経済の合理性に反しています。
 米国ではオバマ氏が大統領に就任し、日本でも民主党が政権の座に就きました。今度は経団連も変わらなくてはなりません。米日両方の民主党が苦戦しているように、経団連の変革も容易ではないはずですが、米倉氏は手腕を評価されているものとみられますので、やる気さえあれば不可能ではないはずです。
 無論、氏が奥田氏や御手洗氏のような方針・思想で事に臨むなら、国民の信頼を得ることなどできようはずがなく、民主党との距離を縮めるのも難しく、下手をすると自民党との蜜月も続かなくなり、旧体制を引きずってしまうことになりますが、氏はまたマラリア予防の蚊帳を開発するなどの活躍もあり、もしかすると今までの会長よりも大義が見える人かもしれません。大変に困難な道のりではありますが、果たして経団連は「大企業の、大企業による、大企業のための組織」から脱皮できるのでしょうか。

 続・MapKey。前回は@MapKeyJoinColumnを使用しましたので、今回は@MapKeyColumnを使用してみます。
 @MapKeyJoinColumnでは、キーとして何らかのEntityを使用していました。すなわち、@OneToManyのOne側のEntityとMany側のEntityに加え、キーの役目を持つEntityも書く必要がありました。当然のことながら、テーブルも3つ生成されます。例えば前回のコードでは、次の3つのテーブルが生成されました。
(キーにあたるテーブル)
mapkeyjoin_account
+------+----------+
| id   | name     |
+------+----------+
| 8751 | 現金     |
| 8752 | 当座預金 |
| 8753 | 売掛金   |
...

(One 側)
mapkeyjoin_office
+------+----------------+
| id   | name           |
+------+----------------+
| 8758 | 北朝鮮支店     |
| 8763 | ミャンマー支店 |
| 8768 | 阿久根支店     |
+------+----------------+

(Many 側)
mapkeyjoin_value
+------+---------+---------+--------+
| id   | price   | account | office |
+------+---------+---------+--------+
| 8759 |  350000 |    8753 |   8758 |
| 8760 |  150000 |    8751 |   8758 |
| 8761 |  800000 |    8754 |   8758 |
...
 @MapKeyColumnは@MapKeyJoinColumnと似ていますが、何らかのEntityをキーにするのではなく、カラムのデータがそのままキーとなるようです。すなわち、上記の例を@MapKeyColumnで書き換えるなら、テーブルは次のようになります。
(One 側)
mapkeyjoin_office
+------+----------------+
| id   | name           |
+------+----------------+
| 8758 | 北朝鮮支店     |
| 8763 | ミャンマー支店 |
| 8768 | 阿久根支店     |
+------+----------------+

(Many 側)
mapkeyjoin_value
+------+---------+----------+--------+
| id   | price   | account  | office |
+------+---------+----------+--------+
| 8759 |  350000 | 売掛金   |   8758 |
| 8760 |  150000 | 現金     |   8758 |
| 8761 |  800000 | 受取手形 |   8758 |
...
 これはすなわち、@MapKeyJoinColumnに比べて以下のような特徴があるとみなせます。

・キーにあたるデータはカラムに記録されるため、別のテーブルは生成されない。
・キーがカラムに記録される性質上、カラムに記録できるデータ以上のものはキーにできない。

 つまり、キーとなるデータに色々な属性を持たせたい場合、あるいは同じ名前のキーが複数存在しかねない場合には、@MapKeyJoinColumnの方が適任であるといえます。
 前者の例としては、以下のようなものが挙げられます。
id	name	type	genre	...
1	現金	借	資産
2	買掛金	貸	負債
3	売上	貸	収益
 この場合、勘定科目に色々なデータが含まれているため、単にString型のキーだけでは対応しきれません。
 後者の例としては、ややいい加減ではありますが、以下のようなものが挙げられます。
id	title
1	支店長
2	支店長補佐
3	支店長補佐
4	経理部長
...
 これをStringで表現しようとすると、"支店長補佐1"などのようにしなくてはなりません。
 また、使用するキーはあらかじめほとんど決まっていて、普段はその中から選択して使用すれば事足りるものの、場合によっては後からキーを新たに登録しなくてはならず、プログラム的に定数としてキーを定めておけないような場合にも、@MapKeyJoinColumnの方が便利です。勘定科目はまさにこの例に当てはまる代表格です。
 一方、特にそうした事情がないのであれば、@MapKeyColumnでも特に問題はなさそうです。単に文字列によるマップを使いたいだけであれば、@MapKeyColumnの方が分かりやすいでしょう。
/WEB-INF
 /classes
  /com
   /yamicha
    /mapkeyjoin
     Program.java
     Command.java
     MapKeyAccess.java
     MapKeyServlet.java
  /META-INF
   persistence.xml
 persistence.xmlは前回と同様です。
<?xml version="1.0" encoding="UTF-8"?>

<persistence version="1.0" xmlns="http://java.sun.com/xml/ns/persistence">
  <persistence-unit name="MySQL" transaction-type="JTA">
    <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
    <jta-data-source>jdbc/MySQL</jta-data-source>
    <properties>
      <property name="eclipselink.jdbc.driver"
        value="com.mysql.jdbc.Driver" />
      <property name="eclipselink.ddl-generation"
        value="create-tables" />
      <property name="eclipselink.ddl-generation.output-mode"
        value="database" />
      <property name="eclipselink.target-database"
        value="MySQL" />
      <property name="eclipselink.logging.level"
        value="FINE"/>
    </properties>
  </persistence-unit>
</persistence>
 ソースは以下の通り作成しました。ただ、今回も1箇所ほど不可解なプロパティがあります。いつもながらサンプルデータは非常に適当です。
// Program.java
package com.yamicha.mapkey;

import javax.persistence.*;
import java.util.*;

@Entity @Table(name="mapkey_program" , schema="yamicha")
	public class Program implements java.io.Serializable{
	private int id;
	private String name;
	private String developer;
	// 今回のキーは String
	private Map<String , Command> commands;

	public Program(){
		commands = new Hashtable<String , Command>();
	}
	public Program(String s , String d){
		this();
		name = s;
		developer = d;
	}

	@Id @GeneratedValue @Column(name="id") public int getId(){
		return id;
	}
	@Column(name="name") public String getName(){
		return name;
	}
	@Column(name="developer") public String getDeveloper(){
		return developer;
	}
	@OneToMany(fetch=FetchType.EAGER ,
		cascade=CascadeType.ALL , mappedBy="program")
		@MapKeyColumn(name="command_type")
		public Map<String , Command> getCommands(){
		return commands;
	}

	public void setId(int i){
		id = i;
	}
	public void setName(String s){
		name = s;
	}
	public void setDeveloper(String s){
		developer = s;
	}
	public void setCommands(Map<String , Command> c){
		commands = c;
	}

	public void link(){
		for(Command c : commands.values())
			c.setProgram(this);
	}
}

// Command.java
package com.yamicha.mapkey;

import javax.sql.*;
import javax.persistence.*;

@Entity @Table(name="mapkey_command" , schema="yamicha")
	public class Command implements java.io.Serializable{
	private int id;
	private String name;
	private String command_type;
	private Program program;

	public Command(){
	}
	public Command(String s){
		name = s;
	}

	@Id @Column(name="id") @GeneratedValue public int getId(){
		return id;
	}
	@Column(name="name") public String getName(){
		return name;
	}
	@ManyToOne @JoinColumn(name="program")
		public Program getProgram(){
		return program;
	}
	@Column(name="command_type") private String getCommandType(){
		return command_type;
	}

	public void setId(int i){
		id = i;
	}
	public void setName(String s){
		name = s;
	}
	public void setProgram(Program p){
		program = p;
	}
	private void setCommandType(String c){
		command_type = c;
	}
}

// MapKeyAccess.java
package com.yamicha.mapkey;

import javax.ejb.*;
import javax.annotation.*;
import javax.persistence.*;
import java.util.*;

@Remote @Stateless(name="MapKeyAccess" ,
	mappedName="ejb/MapKeyAccess")
	public class MapKeyAccess{
	@PersistenceContext(unitName="MySQL") private EntityManager em;

	public void regist(){
		Program java = new Program("Sun Java" ,
			"Sun Microsystems");
		java.getCommands().put("Compile" , new Command("javac"));
		java.getCommands().put("Execute" , new Command("java"));
		java.link();
		em.persist(java);

		Program mono = new Program("Mono C#" , "Novell");
		mono.getCommands().put("Compile" , new Command("gmcs"));
		mono.getCommands().put("Execute" , new Command("mono"));
		mono.link();
		em.persist(mono);

		Program ada = new Program("GNAT" , "AdaCore");
		ada.getCommands().put("Compile" , new Command("gnatmake"));
		ada.link();
		em.persist(ada);

		Program perl = new Program("perl" , "Larry Wall");
		perl.getCommands().put("Execute" , new Command("perl"));
		perl.link();
		em.persist(perl);
	}
	public List<Program> getPrograms(){
		return (List<Program>)em.createQuery(
			"SELECT p FROM Program p").getResultList();
	}
	public Program getProgram(Object id){
		return em.find(Program.class , id);
	}
}

// MapKeyServlet.java
package com.yamicha.mapkey;

import javax.servlet.annotation.*;
import javax.ejb.*;
import javax.annotation.*;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.persistence.*;
import java.io.*;
import java.util.*;

@WebServlet(name="mapkeyservlet" , urlPatterns={"/*"})
  public class MapKeyServlet extends HttpServlet{
  @EJB(beanName="MapKeyAccess") private MapKeyAccess ma;

  public void doGet(HttpServletRequest request ,
    HttpServletResponse response) throws IOException{
    doPost(request , response);
  }
  public void doPost(HttpServletRequest request ,
    HttpServletResponse response) throws IOException{
    response.setCharacterEncoding("UTF-8");
    response.setHeader("Content-type" , "text/plain;charset=UTF-8");
    PrintWriter out = response.getWriter();

    ma.regist();

    List<Program> programs = ma.getPrograms();
    for(Program p : programs){
      out.println(p.getName() + " (" + p.getDeveloper() + ")");

      Map<String , Command> commands = p.getCommands();
      for(Map.Entry<String , Command> e : commands.entrySet())
        out.println("t" + e.getKey() + ": " + e.getValue().getName());

      out.println();
    }

    out.close();
  }
}
 前回に引き続き、commandTypeプロパティは必要なのか非常に謎です。当然ながらprivateにしてあります。
 これを実行すると、以下の結果が得られます。
Sun Java (Sun Microsystems)
	Execute: java
	Compile: javac

Mono C# (Novell)
	Execute: mono
	Compile: gmcs

GNAT (AdaCore)
	Compile: gnatmake

perl (Larry Wall)
	Execute: perl
 テーブルは次の通りです。
mapkey_program
+------+------------------+----------+
| id   | developer        | name     |
+------+------------------+----------+
| 8741 | Sun Microsystems | Sun Java |
| 8744 | Novell           | Mono C#  |
| 8747 | AdaCore          | GNAT     |
| 8749 | Larry Wall       | perl     |
+------+------------------+----------+

mapkey_command
+------+--------------+----------+---------+
| id   | command_type | name     | program |
+------+--------------+----------+---------+
| 8742 | Execute      | java     |    8741 |
| 8743 | Compile      | javac    |    8741 |
| 8745 | Execute      | mono     |    8744 |
| 8746 | Compile      | gmcs     |    8744 |
| 8748 | Compile      | gnatmake |    8747 |
| 8750 | Execute      | perl     |    8749 |
+------+--------------+----------+---------+
カテゴリ [開発魔法][社会問題][経済・知的財産] [トラックバック 0][コメント 0]

[1] [2] [3] [4] [5] 次のページ->
- Blog by yamicha.com -