yamicha.com's Blog - Presented by yamicha.com
Blog yamicha.com's Blog - 2018/10 の記事
[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] [31]

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 件の中から 31-35 件を表示しています。
モノ言う犯罪者
2007/07/21(Sat)21:48:20
 検察の逮捕劇から1年以上が経過し、ようやくグリーンメーラー・村上被告に懲役2年、追徴金11億円の実刑判決が下りました。言うまでもなく当然の判決です。まずあり得ないとは考えていましたが、まさか「無罪」などという判決が下るのではないかと少々ヒヤヒヤしていました。
 関係者の話によれば、村上被告も当初は「モノ言う株主」の志を持っていたのかもしれません。その志のためにファンドを立ち上げたのか、最初からグリーンメールでボロ儲けをするのが目的であったのか、そればかりは本人にしか分かりませんが、少なくとも逮捕直前の村上ファンドは自己利益のためだけにルール違反をいとわない存在であったことだけは確かです。これを適正に評価すれば、実刑以外の判決はあり得ません。
 この裁判での直接の罪状は「インサイダー取引」ですが、これに対する被告人の発言は実に3パターンも存在しています。当初は「聞いちゃった」などと称してインサイダーの事実を認め、その後にはさらに踏み込んで「けしかけた」事実をも認たものの、後になって「嘘をつきました」「私は法を犯す人間ではない」。結局、裁判では「けしかけた」事実を認定し、被告人の姿勢を厳しく非難しています。
 村上ファンドとライブドアの行動をまとめると、次のようになるでしょうか。まず、村上ファンドはニッポン放送の株を手に入れてはみたものの、売り抜ける機会を逃してしまいました。「見切り千両」という言葉はこのような場合のためにあるのでしょうが、利益に目がくらんだ上にファンドとしてのプレッシャーにさらされた村上被告には、もはや「損失(利益)確定」を選択する発想はなかったのでしょう。
 そこで、村上被告は一計を案じました。ライブドアをたきつけてニッポン放送株を高騰させ、売り抜けようというのです。なぜライブドアを使ったのかは定かではありませんが、おそらく社長の世間知らずぶりを目にして「こいつならいける」と考えたのでしょう。村上被告は堀江被告をおだてて信用させ、この計画を実行に移すことにしました。まさに「バカもおだてりゃ木に登る」の言葉がピッタリの状況です。
 村上被告は「株主総会ではライブドアに協力」することをライブドア側に伝え、もくろみ通りライブドアは乗り気になったようです。さらに「時間外取引」の裏技をライブドアに紹介したようで、ライブドアは早速時間外取引を用いてニッポン放送株をかき集め始めました。余談ながら、この資金調達にはリーマン・ブラザーズ証券がかかわっており、同証券は株式転換付社債でかなりの利益を確保したようです。
 村上ファンドはまずライブドアに一部株式を売却して利益を確定し、ライブドアの行為によってニッポン放送株が高騰したところで残りの株を売却、30億円の利益を手にしました。これで村上被告のもくろみはほぼ成功したことになります。その後、ライブドアはフジテレビを脅迫して自社系列会社の株を買わせたり、協力契約を結んだりしましたが、堀江被告ら逮捕とライブドアの没落を受けて契約は解消、今に至ります。
 つまり、例の騒ぎであれほど注目されたライブドアは単に村上ファンドの操り人形にされていたに過ぎず、あの無益な騒ぎで儲けたのは村上ファンドとリーマン・ブラザーズのみ、というわけです。事件後になってようやく証券取引法が改正され、時間外取引が制限されるとともに罰則も強化されたのではありますが、後手に回った印象は否めません。
 村上ファンドを「モノ言う株主」などとして英雄扱いしたマスコミの責任も否定できません。そもそも「モノ言う株主」とはどのような株主のことなのでしょうか。私が考えるに、その会社の株を長期的に保有し、営業キャッシュフローが順調で負債も不安材料もないのに設備投資が非常に小さいような場合に「設備投資すべき」と主張したり、高値を提示する買収者が現れても将来性がないと判断したら突っぱねるなど、会社の長期的な利益を第一に考えて、時にはあえて苦言を呈する人のことではないでしょうか。
 果たして、自身が大株主であることを利用して「タコ配当」を迫ったり、株式の高騰を狙って「身売り」を要求したりする行為が、「モノ言う株主」であるといえるのでしょうか。前者と後者の株主が存在するとして、どちらが「モノ言う株主」にふさわしいでしょうか。おそらく考えるまでもないことでしょう。村上ファンドは単に自己利益のみを考えている存在でしかなく、「モノ言う株主」ではありません
 ひとまず実刑判決と厳しい追徴金を評価します。村上ファンドの行為を考えれば懲役2年でも低すぎるほどですが、そういう規定なのですから仕方ありません。村上被告は即座に控訴したようではありますが、堀江被告にも村上被告にも厳罰をもってあたるのは当然でしょう。

 今度は麻生氏が「アルツハイマーの人でも分かる」発言。「産む機械」発言よりは騒がれていませんし、影響自体もさほど大きくはならないでしょうが、私としては自民党・安倍内閣への支持や投票行為に「狭く深く」結びつくものであると考えています。つまり、この発言で自民党・安倍離れする人の数量自体は少ないものの、その少数の人々の心象は著しく悪化したであろう、ということです。
 それというのも、アルツハイマー患者を抱える関係者の苦労は想像を絶するものであるといいます。一般の認知症(つまり「ぼけ」「老人性痴呆」)でさえ介護が大変であったり、場合によっては無理心中といった事件も目にしますが、それが加齢による生理的な衰えではなく病的なものであるとしたらどうでしょう。なおさら介護が困難なのは容易に想像できます。しかも「若年性アルツハイマー」なるものも存在し、青年や中年でも発症することがあります。
 そればかりか、アルツハイマーにかかった患者本人の苦しみも想像を絶するようです。「患者本人は忘れるのだから幸せ」などという悪意に満ちた偏見もありますが、アルツハイマーといっても本人の意識がなくなるわけではありません。自分が「忘れ病」であることを自覚し、当たり前の記憶が次から次へと失われ、日に日に脳が使い物にならなくなっていく自分を見つめるのにどれほどの苦痛が伴うのかは、アルツハイマーではない私からは想像もできません。
 しかも、絶対にアルツハイマーにならない方法などというものは存在しません。それまで何の問題もなかった人が、突然不自然なミスを繰り返すようになり、その原因が物忘れと気づいた時にはかなり病状が進行していた、といったケースが多いようです。今は健康な人であっても、1年後にアルツハイマーではない保証などどこにもないのです。
 そうした意味で、おそらくアルツハイマーに関係ない人の多くは麻生氏の発言を受け流すことでしょうが、初期のアルツハイマー患者や患者を抱える人々は自民離れを起こすものと考えられます。これを票数に換算すれば微々たるものでしょうが、こうした発言の積み重ねが選挙を決める、かもしれません。
 他にも政治・選挙についていくつか述べておきましょう。ここへ来て内閣支持率が少々回復しました。どうやら地震に対する素早い対応と、年金支給漏れへの対策が評価されたようです。しかし、地震に関しての迅速な対応は当然として(選挙前なら迅速に対応され、選挙後なら対応されないならそちらの方が問題)、年金漏れに関しては何も変わっていないはずです。可能性がある人は自ら出向かなくてはなりませんし、第三者委員会に訴えるには証拠書類が必要です。それには社会保険庁を通さなくてはなりませんが、ここで社会保険庁が否と言えば否なのです。何度も調査を訴えてようやく認められた人もいますが、この人が途中であきらめていれば永久にそのままになっていたでしょう。さらに、支給漏れ分に利子はつきません。
 政治資金についても状況は何ら変わっていません。「対象を限る上に5万円以上」などというザル法を通した挙句、赤城農相が「このザル法において領収書を出さなくても良い」不正を行っていたことについては説明責任を果たさず、領収書も隠蔽し、どうやらザル法を修正する気もない模様です。
 つまり、前回の調査時とでは状況はほとんど変わっていないのです。状況が変わっていないのに支持率が変化するというのは極めて不自然です。有意差が見られるほど変化があったということは、少なくともそれなりの人数が支持に鞍替えしたのでしょうが、一体どういうわけでしょう。こういう世論の考えは私には全く理解できないのですが。
 内閣を支持するか支持しないかは個人の考えですから何も言いません。しかし、何も変わっていないのに、以前は不支持にしておきながら、いきなり支持に戻るようなことはしないでください。それをするなら最初から支持のままでいれば良いでしょう、というのが本音です。このような人が存在すると、選挙の結果がタイミング次第で決まってしまいかねないのです。「今回はA党が勝利したが、3日前に選挙があったらB党が勝利していただろう。ただし、その3日間には何も起きなかった」といった選挙はあまりに不自然です。
 もう1つ、高知の自民党・田村候補が「美しい国などと適当なことばかり言われたら、バカにされている気がする」と安倍氏を痛烈に批判し、「報復」として安倍氏が高知入りを見送りました。よくぞ言ってくれました。私も最近は「美しい」と聞くだけで気分が悪くなっていましたので、この発言には強く同意します。自民党の横暴は勘弁なりませんが、田村氏だけは応援します。ぜひとも「自民党大敗、しかし高知は自民党安定勝利」を実現して欲しいです。

 ところで、ここでふと気になりました。(小)選挙区では得票の多かった候補のみが当選し、議員の座を獲得できなかった候補はどれほど票数が多くても落選します。1票差でも勝ちは勝ち、負けは負けです。したがって、1票の重みはかなりのものになることが分かります。それでは、あいまいに解釈できるような票が存在する場合、その票はどのように解釈されるのでしょうか。
 選挙といえば堅苦しいイメージが存在するようですので、たまにはこのようなお遊びも良いでしょう。以下に考えられるパターンと私の個人的見解を記載しておきます。私の知る限りで決定なり判例なりがある場合、その結果もあわせて示してはいますが、国政選挙ではなく地方選のものも混ざっていますし、毎回同じ判断がなされるとも限りません。また、以下の見解自体も国政選挙に限定するものではありません。その旨ご了承ください。

・投票した候補の氏名に敬称がつけられている場合
 「あべ氏」「おざわさん」「ふくしま議員」「いとう市長」「いしはら知事」など。
 一応「候補者の氏名以外は書かないこと」と決められてはいるのですが、この場合は当該候補に加算されるでしょう。厳密に言えば無効票なのでしょうが、呼び捨てで書くのは、と考えてしまうのも人情です。

・候補に敬称があり、しかもそれが明らかに実際と異なっている場合
 政治経験のない新人に「すずき議員」、ビジネスマンから立候補した人に「たなか先生」などで、しかも名前からして該当する候補が他に存在しない場合。
 一体どうなるのでしょう。これが「小泉首相」などであれば、政治に関心がない層が「今の首相って小泉さんじゃないの?」などと言い出しそうですから、投票者の意思を推測して小泉票になる可能性はあるとして、明らかにそうした推測の余地がない敬称がつけられていたら。やはり名前だけで判断でしょうか。

・票に余計なことが書かれている場合
 「氏」や「さん」であればおそらく許されるでしょうが、その他の「余計なこと」はどこまで許容されるのでしょうか。チェックマーク、星印、丸印など。似顔絵などが描かれていたら、おそらく無効票にされます。なお、以前にアザラシのタマちゃん問題が発生した際、タマちゃん保護を訴える候補への票のうち十数票にアザラシの落書きがしてあり、無効にされたそうです。
 しかし、投票用紙には「候補者の氏名以外は書かないこと」などとルビ付きで説明してあるのに、どうして落書きしようと考えるのでしょう。投票権が3歳から認められているなら仕方ありませんが。まさか20歳にもなって注意書き(しかもルビ付き)も読めないのでしょうか。そもそも「投票」や「候補者」といった漢字にルビが付けられていることからして、奇妙といえば奇妙なのですが。文盲であったり、日本国籍を持ちながら海外で育って帰国など、事情があって漢字があまり読めない人のことを考えての対策でしょうか。

・候補抹消後、同じ名前の人が立候補
 いとう候補が存在したものの、やむを得ない事情(病気・死亡など)で候補から抹消され、補充時に別人のいとう氏が立候補した場合など。
 この場合、実際の投票ではともかく、期日前投票で「いとう」と書かれたものが投票されている可能性もあるわけですが、一体どうなるのでしょうか。抹消されたいとう氏に投票した人からすれば、釈然としないことでしょう。まさか同姓同名ということはめったにないでしょうから、フルネームで書けば予防できそうですが、「いとう」だけならどうなることか。この現象は長崎市長選で発生する可能性がありました。娘の配偶者という人が立候補していましたが、この人が結婚の際に「妻の氏」をチェックして婚姻届を出していたら、実際に「いとう候補」になっていたでしょう。

・上記の場合で、明らかに前の候補を意図した敬称が書いてある
 現職市長のいとう氏が抹消され、他のいとう氏が立候補した場合で、「いとう市長」と書かれた票など。
 これは本当にどうなるのでしょう。書かれている名は明らかに「いとう」、しかし投票者が意図したのは前の候補でしょう。やはり無効にするのが投票者の意思を尊重していると考えるべきでしょうか。

・紛らわしい候補者名にプレフィックスがつけてある場合
 比例区で「ふくだ」候補が2人(死人党及び眠主党候補)いる場合に「死人党ふくだ」など。
 投票者の意思を尊重する意味では、死人党のふくだ氏に加算すべきでしょうか。厳密には「候補者の氏名」以外のことが書かれているわけですが。

・プレフィックスがある上、フルネームまであり、しかもプレフィックスとフルネームに齟齬が生じている場合
 比例区で「死人党・あそう太郎」と「眠主党・あそう次郎」がいるとして、「死人党あそう次郎」と書いてある場合など。
 何とも解釈のしようがありません。無効票でしょうか。

・名前の読み方の勘違いと考えられる場合
 「高村(こうむら)」候補が存在し、他に類する名前の人が存在しない場合で、「たかむら」票など。
 おそらく候補者の上の名前がひらがなで書いてあるのはこれのせいでしょう。せっかくひらがなで書いてあるのですから、読み間違えないようにしましょう。しかし、一体この票はどうなるのでしょうか。投票者の意思としてはこうむら氏なのでしょうが、無効にしなければ不公平な気もします。

・漢字が間違っているが、読み方は正しい場合
 「谷垣」候補が存在し(候補者名は「たにがき」表記)、「谷柿」票がある場合など。
 この場合もどうなるかは気になるところです。他には「本多」候補が存在し、しかも他に類する名前の候補が存在しない場合に「本田」票など。かなり微妙なケースではないでしょうか。

・漢字が間違っており、読みも違うのだが、意図している相手が分かる場合
 「萩原」候補が存在し、「荻原」票がある場合など。この名に類する候補は他に存在しない。
 これも微妙なケースです。誰に投票しているのか、意図を推測することは一応できますが、名前が間違っているという。しかし、部首の書き間違えは誰にでもあるでしょうし、達筆文字や省略文字を書く投票者もいると考えられますので、この程度なら萩原氏に加算されるかもしれません。

・氏と名が異なる候補のものをそれぞれ参照しており、しかもそれらの名前が双方とも個性的なものである場合
 「東国原英夫」と「田中角栄」候補がいるとして、「東国原角栄」など。
 おそらく無効でしょう。意図が読みきれません。

・上記と類似だが、どちらの候補に投票しようとしたか推測できなくもない場合
 「あべ(安倍)しんぞう」と「あべ(阿部)ともこ」という候補がおり、「阿部しんぞう」と投票があった場合など。
 これも微妙なケースです。私なら安倍票と見ますが、無効にすべきかもしれず。

・身体あるいはその他の特徴のみを書いた票
 「ヒゲ」「ハゲ」「背の高い人」「女性」など。ただし、それらに該当すると考えられる人は当該選挙区に1人しかいない。
 私なら無効票と判断しますが、はてさて。このような抽象的なものを含めると、「ハンサム」やら「カッコイイ」やらといった主観の入るものまで処理することになりかねません。そのようなものを書いて投票する人間がおかしいのですが。
 類する問題としては、「タマちゃん」票がタマちゃん保護を掲げた候補に投票されたものであると認められたことがあります。しかし、20過ぎた良い大人が「タマちゃん」などと書いて投票しますか、普通。アザラシ好きなのは構いませんから、候補者程度は名前で書くべきでしょう。

・同名の候補がおり、名前と身体的特徴などを書いた票
 「菅直人」と「菅直子」候補がおり、「菅 女性」などと書かれている場合など。
 これは「投票者の意思が明確である」と判断して菅直子票とすべきでしょうか。しかし「美形の方のあべ」などと書いてある票は分類不可能でしょう。どこを「無効」の線引きにすべきかは非常に疑問です。今回の例でも、もし菅直子氏が性転換手術などで女性になった人であるとして、日本の性転換制度は非常に制限が多いため、戸籍上の性別が変更されていなかったとしたら、どうなるのでしょう。
 身体的特徴ということでは、裁判で「バンド ヒゲ」票がヒゲの「坂東」票と認められたことがありました。

・書き損じ・覚え損じの可能性がある票
 「ひがしこくばる」候補がいる場合に「ひがしこくはら」など。
 「やまざき」候補がいる場合に「やまさき」などであれば、やまざき票にするということで異論はないでしょう。では、濁点程度ではなく明らかに名前を間違えている場合には。「おから」と書いてあった票が、裁判の末に「岡田」候補に加算されたことはありますが、ある意味レアケースでしょう。

・ルビが振ってある場合
 「ひがし」及び「あずま」候補がいる場合で、「東(あずま)」とルビが付けてある場合など。
 これは一目瞭然、あずま候補行きでしょう。「候補者の氏名以外は書かないこと」とされていますが、ルビは「候補者の氏名」に含まれるのでしょうか。

・ルビが振ってあり、逆にそのせいで混乱する場合
 「ひがしこくばる」候補と「あずま」候補がいて、「東(ひがし)」とルビが付けてある場合など。
 「東」だけならあずま票でしょうが、ルビのせいで大混乱。これは無効でしょうか。

 色々と気になることは多いのですが、このような場合にどうするかはともかく、自分の票を無効にしないためには唯一絶対解があるのが救いです(ただし期日前投票後の候補者死亡などを除く)。候補者の氏名は枠内に正しく書きましょう。あだ名ではなく登録名を書き、同じ氏または名の候補が存在する可能性があるので、(特に比例区の)候補者の名前はフルネームで書くのが安全です。もちろん落書きなどしてはいけません。部首の間違いなどを避けるため、名前は候補者名の掲示を丸写しするのが無難です。しかし、これさえ守れば無効票になることはまずありませんが、これらは本来投票権を持つ大人に説明することではないはずです。投票権を持っていても投票できるだけの能力を備えているとは限らないといいましょうか。
 個人的には「小泉郵政選挙とその前後の衆参選挙における、白票とやむを得ないミスによる無効票を除いた無効票の数」を出して欲しいです(おそらくそのような記録は存在しないでしょうが)。低IQ選挙ではその数量が突き出しているのではないかと考えられます。この辺は公表されていないらしいため、実際のところは知りませんが、投票用紙に当時の小泉首相の似顔絵が書いてあったり、「小泉さん ガンバレ!」などとエールが書いてあって無効になったものも存在するのではないでしょうか。後は小泉立候補地でない小選挙区や比例区で「小泉首相」と書いて投票して無効など。「候補者(こうほしゃ)の氏名(しめい)以外(いがい)は書(か)かないこと」などとご丁寧にルビ付きで書いてあっても読めない人がいるわけです。

 DualKnight 3D企画。難問に直面していましたが、ようやくひらめきました。これでスポットライト光源を「照射するピクセル位置を指定」して使えるようになり、パラレル光源及び拡散光の問題2つのうち1つが片付きました。ただ、後者についてはまだ問題とは確定していない「懸念材料」が1つあり、もしこの懸念が無用であれば残る問題1つを解決すれば実装できるのですが、この懸念が本物なら問題が残り2つとなります。
 今回解いた問題は「特定のピクセルへの方位を3つの軸の回転角で表現する」というものです。最初はタカをくくっていたものの、実際には単にアークを使うだけでは実現できないことが分かり、散々迷うハメになりました。ここまで来ると問題が難しくて困ります。
 特に詰まった場合が問題です。単なる実装であれば、コツコツ進めていけば必ずゴールに行き着くのですが、詰まった場合はそうはいきません。良い方法をひらめかない限り進めないのです。しかもひらめきは「問題を思考している時」に訪れるものですから、問題を考えない限りはひらめきません。しかし、問題を考えていても必ずひらめく保証はありません。この辺りのジレンマが辛いところです。
 それにしても素晴らしきATAN2。ExcelとJavaでは引数の順番が逆になり、混乱を招くことはあるものの、相変わらずガンガン活躍してくれました。右手座標系においてはX及びY軸回転をそのまま計算すると時計回りになってしまう(通常、三角関数は反時計回り)ため、Z座標の正負を反転して渡したりしなければなりませんが、そうした点に気をつければ強力すぎる武器です。DualKnight 3DではMath.atan2以外のアークを使っていませんが、これは単に計算の手数が少なくて済むからであり、アーク系は基本的に相当使えます。

 それでは、今回の進捗状況を画像で表してみるとしましょう。以下の場面はどれも同じ視点・同じ条件・同じ照射点にてスポットライトの位置のみを変えたものです。今回の実装により、指定した照射点ピクセルの位置と光源の位置から光の向きが自動計算され、スポットライトをどこに置いても指定したピクセルの方角を向くようになっています。


 最初の状態です。スポットライトは上空600の位置から真下に向けています。光の有効射程は3200、カラーは黄色(RGB指定なら#FFFF00)、減耗なし半径が11.75度、減耗あり半径が45度です。光源からマテリアルまでの距離が離れるほど、またマテリアルが光の中心からずれるほど光は減耗していきますが、減耗なし半径の範囲内であれば中心からずれることによる減耗はありません(距離による減耗は起こります)。視点はやや左側から軽く右向きです。


 光源を高さはそのままで左側かつ手前に移動した図です。つまり、上空左側手前からの照射になります(左側とはいっても、そもそも視点を多少左側に移動してあるため、この視点からすればおおむね背後からになります)。真上からの照射と違い、上空の三角形にも光が当たっていることが分かります。下の三角形の最も明るいところが光の中心なのですが、光はそこから45度も拡散するため、上空の三角形もその範囲内に入っています。


 上記の光を地表すれすれまで移動した図。減耗なし半径の部分がくっきり現れています。上空の三角形については、さすがに減耗なし半径の部分からは外れているでしょうが、角度が光の中心点に比較的近い上、光源を地表スレスレまで持ってきたことで光源との距離も縮まっているため、かなり鮮明に光を浴びています。


 おおむね真上から照射しつつ、光をかなり低い場所まで移動した図です。スポットライト光源の原理は懐中電灯と同じですから、当然ながらこのような結果になります。原理が良く分からない人は、懐中電灯を床に向けて試してみましょう。床に近づけると光は強くなりますが、その分範囲は狭くなります。


 こちらは逆に光源を上空に移動してみた結果です。上空の三角形も含めて広い範囲が照らされていますが、強力に照らされている場所はありません。距離による減耗がかなり効いています。

 以上、光源でありました。しかし、光というのも災難なものではありませんか。距離減耗の上に角度でも減耗を受けるのですから。資産が2度も減価償却されているようなものです。さらに、どうやらこの減価償却の計算はPCとしても大変なようで、なかなか重いです。

 オマケ・PHPで三角形を指定した角度だけ回転するプログラム。どこぞの家庭教師は「MotherからMを取ったらOther」などというCMを流していましたが、Angelの最後の文字を入れ替えるとAngle、非常に複雑であり、突き詰めると悪魔です。
<?php
// カンバスのサイズ
$width = 150;
$height = 150;
// 三角形の各頂点の X , Y 位置
$delta = array(
	array(75 , 100) , 
	array(45 , 50) , 
	array(105 , 50));
// 三角形の回転軸
$center = array(75 , 80);

if($_POST["angle"] != ""){
	$img = imagecreate($width , $height);
	$back = imagecolorallocate($img , 0xFF , 0xFF , 0xFF);

	$line = imagecolorallocate($img , 0 , 0 , 0);

	$angle = $_POST["angle"];
	$rad = deg2rad($angle);

	$result = array();
	for($i = 0; $i < 3; $i++){
		$x = $delta[$i][0];
		$y = $delta[$i][1];
		$c_x = $center[0];
		$c_y = $center[1];

		$a_x = $x - $c_x;
		$a_y = $y - $c_y;

		$hypot = hypot($a_x , $a_y);

		$vector = 0;
		if($a_x != 0 || $a_y != 0){
			$vector = atan2($a_y , $a_x);
			$vector += $rad;
		}

		$result[] = cos($vector) * $hypot + $c_x;
		$result[] = $height - (sin($vector) * $hypot + $c_y);
	}
	
	imagepolygon($img , $result , 3 , $line);

	header("Content-type: image/gif");
	imagegif($img);
	imagedestroy($img);

	return;
}
?>
<html>
<head>
<title>Image + PHP</title>
</head>
<body>
<b>Image</b>
<form method="POST">
 三角形を回転する角度を入力してください。<br>
<input type="text" name="angle" value="0">
<input type="submit" value="送信">
</form>
</body>
</html>
 変数$deltaには三角形の各頂点の位置(好きな数値で構いませんが、あまり大きいと画像からはみ出すので注意。大きな三角形を使う際には$widthと$heightの値も大きくしてください)、$centerには回転の軸となる位置を指定します。頂点及び軸の位置のY座標は画面座標と反対(上に行くほど大きくなる)ですからご注意を。アークを使えば既存の三角形をそのまま回転させることができるため、変数には角度その他の指定は必要ありません。どうやら高校の数学にはアークが存在しないらしいため、アーク系を使ったことがない人は戸惑うかもしれませんが、実際には非常に簡単なコードです。ついでにアークの強力さもお分かりいただけるはず。hypotはピタゴラス(三平方)の定理です。
 それにしても2Dは簡単で良いです。Tactical Revolutionでは上記のようなプログラムで三角形をグルグル回転させていたわけですが、手軽かつ軽量にそれなりのエフェクトが作れるため、2Dも捨てたものではありません。
 もしまかり間違って自民党が勝利し、教育バウチャー制度が導入されてしまえば、当然ながら「児童・生徒の点取りマシーン化教育」が横行するようになり、三角関数を創造的に使用できる人は確実に減少する、というのはここで語るべきことではありませんか。本当は数学が苦手な方でも読めるブログを目指すべきなのでしょうが、たまにはこのような記事があっても良いでしょう。
 それにしても、毎回考えていることながら、つくづく分かりやすい記事を書くのは難しいです。突き詰めれば「日本語は難しい」「自分の考えを他人に伝えるのは難しい」ということになるでしょうか。しかし、どうやらこれを難しいものと考えているのは私だけではないようで、政治家連中が好き勝手言ってみた挙句に世論から大非難を浴びているのを見る限り、やはり言論や意思伝達が本質的に難しいことが分かります。政治家の場合は「本音が出ている」のが問題なのですが。
 というのも、私は「産む機械」「アルツハイマーの人でも分かる」などとは口が裂けても言いませんし、書きません。考えてもいないことは言えませんし、ましてや書くことなどできません。「アルツハイマー」発言などは、その発言自体も不快感を与えかねない軽率なものですが、発言を生み出す「土壌」がなおさら問題なのでしょう。
 ここはひとつ、「アルツハイマーの人でも分かる」という発言が失礼であることはアルツハイマーの人でも誰でも分かるが、政治家には分からない、ということで。
カテゴリ [開発魔法][社会問題][経済・知的財産] [トラックバック 0][コメント 0]

ピンハネ連中の品格
2007/07/11(Wed)21:20:56
 フルキャスト、ピンハネした給与の全額返還を発表。あくまで「申請のあった希望者だけ」とのことで、ニュースも見なければピンハネの事実も知らない層の救済にならないのは困りますが、それでも「創業時から約15年分のピンハネを全額返還」というのはなかなかの決断です。請求次第によっては、総額数十億円もの規模になるといいますから、容易ならざる決断でしょう。逆に言えば、それだけの金額が不当にピンハネされていたということです。そもそもピンハネしていたことがおかしいのですから、それを返すのは詐欺の収益金を被害者に返還するのと同様に当然のことなのではありますが、その「当然のこと」をしない企業も存在します。
 毎度のことながら、かのグッドウィルが最近2年以外のピンハネの返還を拒んでいるのです。他にもピンハネした上に返還に応じない企業は存在しそうなものですが、それが生命線という中小企業ならまだしも、まがりなりにも最大手のグッドウィルがこれでは。2年以内の分のみ返還に応じるそうですが、それ以上になると「時効」を理由に応じないそうです。労働組合の「グッドウィルユニオン」は当然ながらこれに反発し、「ピンハネは不当なものであって通常の時効は適用されない」として全額返還を求めています。
 毎日新聞のサイトに元支店長への取材結果が記されているのですが、それによれば「ピンハネ分は収益源」とのこと。派遣業側は「保険である」だの「データ装備費である」だのと白々しい言い訳をしていましたが、実際にはこうした名目は単なる形式上のものであり、収益のためだけにピンハネされていたことになります。どうやら支店はこのピンハネ分を「上納」する義務があったようで、1人分でも欠けると理由を説明しなければならなかったそうです。
 なお、派遣労働者には「保険」などと言いくるめ、脅迫まがいの文句でピンハネに同意させることもあったといいます。しかし、どうやら「保険」などなかったらしく、ケガをしても何ら補償がなかったことを証言する労働者もいます。さらに、「派遣紹介側」という立場の強さを利用し、「ピンハネに同意しないなら仕事を出さない」などという同意の強制が横行していたようです。グレーゾーン金利ギリギリで貸し付けていた悪質な金融業者と本質は全く同じです。こうした事実を隠蔽しつつ、貸金業と派遣業の連中が堂々とテレビや電車でCMを行う世の中とは、嘆かわしい限りです。
 無論、派遣業者だけを責めることはできません。そもそも派遣業自体がピンハネで成り立つ商売なのですから、今回のような形のピンハネを禁じたところで、別のところからピンハネをもくろむだけでしょう。派遣業を認める改正案自体は以前から議論されていながら、ピンハネ発生の可能性を考慮して長らく厳しく制限されてきたのに、それを「規制緩和」の名の下に安易に認めた政治家の責任も重いのです。「先の見えない大不況」を招いた原因の1つはこれでしょう。
 実際、給与の3/4をピンハネされていた例もあるといいます。多くの場合、派遣社員の給与は派遣会社経由で渡りますし、派遣先の企業が派遣社員に対して支払額なり契約額なりを教えることはあまりないと考えられますので、ピンハネ額が1/2だろうが3/4だろうが気づくことは難しいのです。また、気づいたとしても被害者を保護する規定はほとんどありません。
 ここまで来れば派遣業も貸金業と同じです。厳しい制限を課すと同時に、安易に緩和された規制を少しずつ戻していかなければ、このような問題は今後も続くでしょう。また、グッドウィルはすみやかにピンハネ分の全額返済を申し出るべきです。グッドウィル本体といい、先に買収したクリスタルといい、所詮は脱法体質の企業ですから、どこまで期待できるかは不明ですが。

 大慌てのスティール、最高裁に特別抗告。おそらく覆ることは9割方ないでしょうが、日本の多くの企業にタカっているはずのスティールが、単なるブルドックの1件にこれほど必死になるのには理由があります。
 ハゲタカ・グリーンメーラーの暗躍を見ての通り、日本は今のところ攻撃者優位です。突然TOBを仕掛けたり、TOB期間中にその条件を強化したりと、臨機応変な攻撃方法を取ることができます。また、現在でこそ「株式の1/3以上を急速に集める場合はTOBによる」ことが定められていますが、証券取引法改正以前は時間外取引で不意打ちをかけることも可能でした。さらに、ライブドア問題でフジテレビが苦肉の策を講じるも、裁判によってそれが差し止められたように、防御側の行動は非常に限られています。
 とはいえ、日本には「株式の持ち合い」なる鉄壁の防御策が存在した上、ライブドア問題以前までは「時間外取引による買収は合法だが推奨されない」といった程度の定義で誰もそれに手出しをしなかったことを見ても、劣悪なグリーンメーラーは少なかったようです。バブル真っ只中の間はこれでも何とかなったのでしょう。
 ところが、そのバブルが崩壊したからさあ大変。持ち合いの図式は崩れ、株価低迷による割安さから海外のハゲタカが流入してきました。どういうわけか、国内でもハゲタカやグリーンメーラーが寵児扱いされるようになってしまいました。そして何といっても致命的なのは、国内の企業がこれに対する防御手段を備えていないことです。事実、現在の日本は「黄金株は株主の平等に反し、認められない可能性大」「毒薬条項の発動例なし」「ホワイトナイト1つで国民沸騰」という有様です。ブルドックが株式割り当て行為を完遂すれば初めての発動例になります。
 では、ブルドックの毒薬条項が司法のお墨付きを得て発動された場合、日本は一体どうなるのでしょうか。これまでは「作っても発動できるか分からない」という非常に矛盾した存在であった防衛策でしたが、これで一定の信頼性が担保されるようになり、多くの企業がこれの導入を試みるでしょう。また、日本の司法は判例主義であるため、明らかに状況が異なる裁判以外では同様の判決を下すことが期待できます。すなわち、これまでは「持ち合い」か「MBO」程度の対策しか取ることができず、裸一貫も同然であったのが、防衛策の導入によって防御手段を得ることができるようになるのです。
 そうなると真っ青なのがハゲタカファンドやグリーンメーラーの連中です。抵抗の術を持たない住民相手に好き放題に略奪を繰り返していたところ、住民が強力な防御手段を講じたようなものです。さらに、ブルドックやTBSの株主総会において大半の株主が買収防衛策を支持したのを見ての通り、国民は不当な敵対的買収者に大きな不信感を抱いています
 ブルドックでこれが認められれば、他の企業でも同様の防衛策が認められるでしょう。これまで我が物顔で市場を荒らしまわってきたグリーンメーラー連中でしたが、これでは肩身が狭くなるばかりです。事実、ブルドックの勝算が高くなったことを受け、スティールが保有している株式は全体的に値を下げているようです。だからこそスティールはこれを必死になって食い止めようとしているのです。
 逆に言えば、今回のブルドックが買収防衛策発動にこぎつければ、好き勝手に暴れまわってきた買収者も多少は行動しづらくなることでしょう。望ましい傾向です。

 さて、本日は久々にWSDLでもと考えていましたら、驚愕の真実が発覚しました。9.0ではバグがあってWSDLを生成できず、9.0から9.1の比較的早い段階のglassfishにアップグレードした際にはWSDLを生成できたのですが、何と現在使っているglassfishではバグが復元されています。アップグレードした直後に動作確認しなかった私も私ですが、何考えているのやら。「NoClassDefException」ですから、ユーザーレベルで手出しできるものではありません。
 仕方がないので、とりあえずUDDIにアクセスする方法だけでも。どうやらglassfishには自分がUDDIレジストリになる機能はないようです。

1.Admin Consoleの「WebService」を開き、「Registry」タブを開いて「Add」。
2.ドロップダウンから「UDDI 3.0」を選択。適当なJNDI名をつけ、目当てのUDDI(おそらくパブリックUDDIでもプライベートUDDIでも可)のアドレスを入力する。ユーザー名とパスワードは要求されているなら入力。
3.先のJNDI名を使ってjavax.xml.registry.ConnectionFactoryをルックアップできる。createConnection()で接続を生成し、その接続からgetRegistryService()を使ってRegistryServiceを取得し、操作を行える。
4.設定を変更したくなったら、WebServiceタブからでは変更ができないので、「Resources/Connectors/Connector Connection Pool」の当該項目から変更する。

 しかし、せっかくJAXRなるAPIが存在するにもかかわらず、UDDIなどほとんど使われていないようですが。「ネットワーク経由で未知のWSDLを検索できる」とはいいますが、言い換えれば「不特定多数が作成したWSDLの中から、あるいはプライベートUDDIでもいかなる目的のWSDLがアップデートされるか分からない中から、得体の知れないWSDLを検索する」ツールなのですから、当然ではあります。
 それにしても、glassfishでWSDLが使えないのは痛すぎるのですが。あれこれ書こうとしていたのが台無しです。といっても、WSDLがどこまで重要かは疑問を持たざるを得ない部分があります。すでに類する規格まで登場している有様ですし、互換性のないサーバー同士でデータをやり取りする場合でなければWSDLなどお荷物でしかないわけです。当初は「UDDIによるWSDL検索」「1つのWSDLを複数企業間で使いまわし、互換性のあるSOAP XMLを生成」などをもくろんでいたようですが、前者の状況は上記の通りですし、後者はそもそもWSDLやSchemaの仕様さえ分裂しているのに、同種企業間で互換性のあるWSDLなどを作ることが現実的かどうか。最近はこの辺りの理念はどこへやら、ほとんど「Javaと.NETを連携させる方法」と化しています。

 JavaScriptでは「JSON」なるものを使用してデータを表現できます。具体的には、以下の規則に従ったデータ表現を行えば、単にevalを使うだけでそれをJavaScriptデータに変換することができます。
I.数値・真偽・null
そのまま表記
例:1 , -3.5 , 1.0e

II.文字列
ダブルクォーテーションで囲んで表記
ただしダブルクォーテーションとバックスラッシュはエスケープする
\nや\rなどの制御文字を使用可能
例:"This is the \\"Java\\" language\\n"

III.配列
ブラケットで囲んで表記
データはカンマで区切る
例:[10 , 20 , 30]

IV.オブジェクト
{}で囲んで表記
データは「"変数名":値」と表記し、カンマで区切る
例:{"name":"value","name2":"value2"}

・解釈方法
var data = eval('(' + data + ')');
データの両側にカッコを足しているが、これがなくても一部データは動作
オブジェクトをパースする場合はカッコが必要なので注意
 独特の表記ではありますが、PHPのserializeに比べれば大したことはありません。何よりJavaScriptで非常に簡単に扱えるため、JavaScriptへのデータ渡しには活躍しそうです。といっても、単にinnerHTMLに吐き出すような場合には、最初からHTMLで渡せば良いのですが。
 パースが簡単なこともあってか、各言語に様々なライブラリが存在するようです。しかし、この程度なら手書きでも大したことはないでしょうし、パーサを作るのも簡単でしょう。せっかくですからJSPでも使って書いてみましょうか。
 以下、即席でざっと書いてみたパーサの実装です。
private String parse(Object data){
	if(data == null)
		return null;
	if(data instanceof Integer || data instanceof Short || 
		data instanceof Long || data instanceof Float || 
		data instanceof Double || data instanceof Boolean){
		return data.toString();
	}
	if(data instanceof String){
		String str = (String)data;
		str = "\\\"" + str.replaceAll("\"" , 
			"\\\\\\\\\\\\\"") + "\\\"";
		return str;
	}
	if(data instanceof List){
		List l = (List)data;

		int loop = 0;
		String str = "[";

		for(Object o : l){
			if(loop > 0)
				str += ",";

			str += parse(o);
			loop ++;
		}

		str += "]";
		return str;
	}
	if(data instanceof Map){
		Map m = (Map)data;
		Set keys = m.keySet();

		int loop = 0;
		String str = "{";

		for(Object key : keys){
			if(loop > 0)
				str += ",";

			str += parse(key.toString()) + ":" + 
				parse(m.get(key));
			loop ++;
		}

		str += "}";
		return str;
	}
	return null;
}
 適当にしか検証を行っていないため、いくらかバグがあるかもしれませんが、PHPのserializeと比べても驚くべき簡単さです。
 使い方ですが、まず整数・小数・文字列などはそのまま渡します。Java SE 5以降にはオートボクシング機能があるため、プリミティブ型をそのまま渡すことができます。文字列パース部分には「"\\\\\\\\\\\\\""」などという冗談のような記述がありますが、Javaで\\が\と解釈され、また\"が"と解釈されます。JavaScriptのevalで\\が\と解釈されるため、この2つを加味すれば\\\\がようやく\になります。つまり「\\\"」です。ところが、これ自体がJavaScript内の文字列クォート内に存在するため、「\"」は単なるエスケープとみなされます。その前の\\も\と解釈するため、結果的には単なるクォートになるのです。
 配列に関しては、Javaのものをそのままマップしても良いのではありますが、ここではListを用いました。また、Javaのオブジェクトをそのままマップするのは不適切と考えられますので、代わりにMapを使ってマッピングしています。多次元配列を作ったり、オブジェクトの中にオブジェクトを含めることもできます。なお、無限循環に関してはチェックしていませんので、循環を起こさないように注意する必要があります。循環防止の実装自体はさほど難しくありませんが、今回あえて実装する必要性を見出せませんでした。
 それ以外の型については全部nullとみなされますので注意が必要です。また、厳密なチェックは行っていませんので、変数名を空欄にしたりnullにしたりしないようにしてください。
 それでは実際に使ってみるとしましょう。せっかくですからAjaxでも使うべきでしょうか。まずはテーブルでも作成しまして、
CREATE TABLE json_member(number INT , name VARCHAR(32) , 
PRIMARY KEY(number));

CREATE TABLE json_equip(number INT , member INT , 
name VARCHAR(32) , PRIMARY KEY(number) , 
FOREIGN KEY(member) REFERENCES json_member(number) ON DELETE CASCADE);

INSERT INTO json_member VALUES(1 , 'サーラ') , 
(2 , 'シェリー') , (3 , 'イリアス');

INSERT INTO json_equip VALUES(1 , 1 , 'バブルソード') , 
(2 , 1 , 'シールドシールド') , (3 , 1 , 'チェーンメール') , 
(4 , 2 , '企業会計読本') , (5 , 2 , '難しい資料') , 
(6 , 2 , 'シークェルが分かる本') , (7 , 2 , 'ゴールデンクロス') , 
(8 , 3 , 'ネイピア') , (9 , 3 , 'バスローブ') , (10 , 3 , 'ヒヤリハット');
 これをJavaScriptでマッピングできないかを考えます。しかし、JSONで装備品が取得できるとは斬新な。
 json_memberテーブルはオブジェクトにマッピングするとして、json_equipはやはり配列にすべきでしょうか。JSONでは循環構造は表現できませんので、json_memberからの一方通行になりそうです。
 これらを踏まえて作成したのが以下のコードです。
<%@page import="java.util.* , java.sql.* , 
javax.sql.* , javax.annotation.*" 
contentType="text/html;charset=UTF-8" pageEncoding="Shift_JIS" %>

<%!
@Resource(name="jdbc/MySQL") private DataSource ds;

private String parse(Object data){
 if(data == null)
  return null;
 if(data instanceof Integer || data instanceof Short || 
  data instanceof Long || data instanceof Float || 
  data instanceof Double || data instanceof Boolean){
  return data.toString();
 }
 if(data instanceof String){
  String str = (String)data;
  str = "\"" + str.replaceAll("\"" , "\\\\\\\"") + "\"";
  return str;
 }
 if(data instanceof List){
  List l = (List)data;

  int loop = 0;
  String str = "[";

  for(Object o : l){
   if(loop > 0)
    str += ",";

   str += parse(o);
   loop ++;
  }

  str += "]";
  return str;
 }
 if(data instanceof Map){
  Map m = (Map)data;
  Set keys = m.keySet();

  int loop = 0;
  String str = "{";

  for(Object key : keys){
   if(loop > 0)
    str += ",";

   str += parse(key.toString()) + ":" + parse(m.get(key));
   loop ++;
  }

  str += "}";
  return str;
 }
 return null;
}
%>

<%
String mode = request.getParameter("mode");
if("ajax".equals(mode)){
 Connection c = null;
 try{
  c = ds.getConnection();
  Statement s = c.createStatement();
  ResultSet rs = s.executeQuery("SELECT number , name FROM json_member");

  List<Map> members = new ArrayList<Map>();

  PreparedStatement ps = c.prepareStatement(
   "SELECT number , name FROM json_equip WHERE member = ?");

  while(rs.next()){
   Map<String , Object> member = new Hashtable<String , Object>();

   member.put("number" , rs.getInt("number"));
   member.put("name" , rs.getString("name"));

   ps.setInt(1 , rs.getInt("number"));
   ResultSet e = ps.executeQuery();

   List<Map> equips = new ArrayList<Map>();
   while(e.next()){
    Map<String , Object> equip = new Hashtable<String , Object>();
    equip.put("number" , e.getInt("number"));
    equip.put("name" , e.getString("name"));
    equips.add(equip);
   }

   member.put("equips" , equips);
   members.add(member);
  }
  ps.close();
  s.close();

  out.print(parse(members));
 }catch(Exception e){
 }
 c.close();
}else if(mode == null || "".equals(mode)){
%>

<html>
<head>
<title>Test</title>
<script language="JavaScript">
// YAjax
function YAjax(){
 this.YAjax();
}
YAjax.prototype.YAjax = function(){
 this.createRequest();
 this.headers = new Array();
 this.headers.unshift(new RequestHeader(
  "Content-type" , "application/x-www-form-urlencoded"));
 this.active = false;
}
YAjax.prototype.getRequestHeaders = function(){
 return this.headers;
}
YAjax.prototype.setRequestHeaders = function(h){
 this.headers = h;
}

YAjax.prototype.createRequest = function(){
 try{
  this.ajax = new ActiveXObject("Microsoft.XMLHTTP");
 }catch(e){
  this.ajax = new XMLHttpRequest();
 }
}
YAjax.prototype.init = function(){
 if(this.ajax == null){
  this.createRequest();
  if(this.ajax == null){
   return false;
  }
 }else if(this.active){
  this.ajax.abort();
 }

 if(this.ajax != null)
  this.prepareCallback();

 this.active = true;

 return true;
}
YAjax.prototype.cancel = function(){
 if(this.ajax != null && this.active){
  this.ajax.onreadystatechange = function(){}
  this.ajax.abort();
  this.active = false;
 }
}
YAjax.prototype.isSucceed = function(){
 if(this.ajax.readyState == 4 && this.ajax.status == 200)
  return true;
 return false;
}
YAjax.prototype.getAjax = function(){
 return this.ajax;
}
YAjax.prototype.requestCallback = function(){
 this.onStateChange();
 if(this.isSucceed()){
  this.onResponse(this.ajax.responseText);
 }else if(this.ajax.readyState == 4){
  this.onError();
 }
}
YAjax.prototype.onResponse = function(text){
}
YAjax.prototype.onError = function(){
}
YAjax.prototype.onStateChange = function(){
}
YAjax.prototype.prepareCallback = function(){
 if(this.ajax != null){
  var selfobj = this;
  this.ajax.onreadystatechange = function(){
   selfobj.requestCallback();
  }
 }
}
YAjax.prototype.request = function(url , args , method , async){
 this.init();
 this.onRequest(url , args , method , async);
}
YAjax.prototype.onRequest = function(url , args , method , async){
 if(method == null || method == "")
  method = "GET";
 if(url == null)
  url = "";
 if(args == null)
  args = "";
 if(async == null)
  async = true;

 var urls = this.parseURL(url , args , method)

 var ajax = this.getAjax();

 if(!async)
  ajax.onreadystatechange = function(){}

 ajax.open(method , urls[0] , async);

 for(var i = 0; i < this.headers.length; i++)
  ajax.setRequestHeader(this.headers[i].getName() , 
  this.headers[i].getValue());

 ajax.send(urls[1]);

 if(!async)
  this.requestCallback();
}
YAjax.prototype.parseURL = function(url , args , method){
 var send_url = url;
 var send_args = "";

 if(method == "POST"){
  send_args = args;
 }else{
  if(send_url.charAt(send_url.length - 1) != "?" && args != "")
   send_url += "?";
  send_url += args;
 }

 return new Array(send_url , send_args);
}

function RequestHeader(name , value){
 this.RequestHeader(name , value);
}
RequestHeader.prototype.RequestHeader = function(name , value){
 this.name = name;
 this.value = value;
}
RequestHeader.prototype.getName = function(){
 return this.name;
}
RequestHeader.prototype.getValue = function(){
 return this.value;
}

// 実装
var ajax = new YAjax();
ajax.onResponse = function(text){
 var value = eval('(' + text + ')');
 var str = '<table border="1">';
 str += '<tr>';
 str += '<td bgcolor="#CCDDFF">number</td>';
 str += '<td bgcolor="#CCDDFF">name</td>';
 str += '<td bgcolor="#CCDDFF">equip</td>';
 str += '</tr>';
 for(var i = 0; i < value.length; i++){
  str += "<tr>";
  str += '<td valign="top">' + value[i].number + '</td>';
  str += '<td valign="top">' + value[i].name + '</td>';
  str += "<td>";

  str += "<b>Equipments</b>";
  for(var e = 0; e < value[i].equips.length; e++){
   str += "<br />(" + value[i].equips[e].number + 
    ")" + value[i].equips[e].name;
  }

  str += "</td></tr>";
 }
 document.getElementById("result").innerHTML = str;
}
</script>
</head>

<body onload="ajax.request('?','mode=ajax')">
<span id="result"></span>
</body>
</html>

<%
}
%>
 parse()は先に作成したものを流用しただけですし、YAjaxも以前に作成したものをほぼそのまま流用しています。parse()の文字列処理部分の「\」は減っていますが、これは先のコードでデータを文字列に展開していたのを、今回はJavaScriptの文字変数として展開しているためです。文字変数ならその部分でのエスケープの必要がないため、結果的にエスケープシーケンスを減らせることになります。
 参考までに記述しておきますと、「?mode=ajax」では次のようなデータが生成されます。

[{"name":"サーラ","equips":[{"name":"バブルソード","number":1},{"name":"シールドシールド","number":2},{"name":"チェーンメール","number":3}],"number":1},{"name":"シェリー","equips":[{"name":"企業会計読本","number":4},{"name":"難しい資料","number":5},{"name":"シークェルが分かる本","number":6},{"name":"ゴールデンクロス","number":7}],"number":2},{"name":"イリアス","equips":[{"name":"ネイピア","number":8},{"name":"バスローブ","number":9},{"name":"ヒヤリハット","number":10}],"number":3}]

 これをJavaScriptで解析し、整形して表示しているのです。
 それにしても、glassfishでWSDLが使用できないと分かり、急遽JSONを代役に仕立ててみたのですが、ほとんど勢いでパースメソッドまで書けてしまうこの簡単さ。JSONの威力、侮れません。
カテゴリ [開発魔法][社会問題][経済・知的財産] [トラックバック 0][コメント 0]

遊識者会議
2007/06/30(Sat)19:43:53
 暴走すればするほど意味不明の深みにはまる安倍内閣。国民が望みもしないものを自己満足のためだけに成立させ、弱者への配慮のない行動を繰り返し、しかも自己利益のためだけに参院選の日取りまで変え、自治体をてんてこまいさせたり、イベントの予定を狂わせる。1ヶ月あれば強行採決も不祥事も国民は全部忘れているであろうとタカをくくる。やはり安倍内閣は信頼するに値しないということです。安倍内閣の本質は最初から予想していましたが、ここまで的中するとむなしいほどです。
 しかも、強行採決される法案の中身といえば、下手すると成立しない方がマシなものばかりです。国民のためにならない法案を大量に成立させておいて、選挙ではそれを国民のためと見せかけた説明を行って「実績」を強調、さらに1ヶ月の冷却期間で国民は悪行をすべて忘れている、といった筋書きを考えているのでしょう。そのようなバカげた手には乗らない、と言いたいところですが、実際に乗ってしまう人間が存在するからこそ、政府はこの手を仕掛けてくるのです。
 まず社保庁法案ですが、所詮は小手先の対応です。新機構で民間委託を推進したところで、根本的な解決にはなりません。そればかりか、ここに利権が発生する余地も大いにあります。また、先に行われた実験的な民間委託では、民間は容易に数字の出せるところを優先し、仮に重要であっても数字を出しにくいところは優先しない結果が出ています。少人数向けのきめ細かなサービスも切られる傾向にあります。果ては数字のために偽装やら何やらが起こる危険性も捨て切れません。介護も食品も英会話も偽装されていて、年金事業の委託のみ偽装されないと考えるのは虫が良すぎます。また、民間委託といえば聞こえは良いですが、国が面倒を見るべき厄介な業務をすべて民間に丸投げしているだけです。
 さらに、社保庁が怠慢組織であることは論を待ちませんが、これを破壊しようが存続しようが所詮は小手先です。根底にあるのは明らかな制度不満・不信であり、制度そのものを破壊して再構築しなければ意味がありません。制度を機械装置、社保庁をパイプとするなら、装置から黒煙が上がって異音がしているのに、必死になってパイプのみを取り替え、それを国民にアピールしているようなものです。パイプの漏れの封鎖も大事ですが、装置の補修なくしては何の意味もありません。
 極めつけは天下り法。これではほとんど天下りバンクです。「人材バンク」を隠れ蓑にし、実際には天下りをあっせんしてやろうというのが本音でしょう。そういえば社保庁も天下りの温床でしたか。システム開発会社への天下りの見返りとして、十数年で額にして兆単位の仕事を持ってきていたようです。開発技術の習得は極めて難しく、社保庁のお偉方がホイホイ習得できるようなものではありませんし、ましてやそのような社保庁のお偉方が開発の専門知識を買われて迎え入れられるということはまずないと考えられますから、それ自体が利権を使った天下りであることを物語っています。これが人材バンクの目指すところでしょう。
 このように、今回の強行採決ラッシュで支持に値する法案は1つも存在しないのです。年金時効停止措置法についてのみはある程度理解できますが、これは利息が一切つかない点で不当ですし、照合作業なくしては実現すら困難です。言うまでもありませんが、1年そこらでの照合は絶対に不可能です。また、この法案はもともと秋に提出される予定のものですし、野党賛成の上で成立させる余地が十分にあるにもかかわらず、与党の点数稼ぎのダシに使われている印象は否めません。しかも、秋の予定のものをここへ持ってきて、しかもロクな審議もなく成立ということで、与党のくだらない点数稼ぎのためだけに法案の詰めがおろそかになっているのです。十分審議された法案なら救済されていたであろう人が、詰めが甘いこの法案のせいで救済されなかった、といった現象も発生するかもしれません。無論、この場合も政府は責任を取ってはくれません。
 困ったことに、脱北者問題、年金問題、法案強行採決などによって与党の不祥事は次から次へと忘れ去られています。「産む機械」発言の上、信念と情熱をかけて無賃残業合法化制度を推進しようとした厚生労働相、それを弁護するばかりの安倍氏、おそらく不正発覚の糸口を絶つために自殺した農相など、忘れてはならないことが山のようにあります。
 参院選に向けて、与党はあえてこれらの問題を忘れさせるように仕向けている節さえあります。無賃残業合法化制度が作られかけたこと(途中で与党にトラブルがなければ高い確率で成立していました。今後別名での提出の恐れも強いです)、農相が自殺し、おそらくその裏にある政権を揺るがすであろう不正を隠蔽したこと、社保庁が5000万件を宙に浮かせたばかりか、システム開発会社との癒着があるらしいこと、国民にとって利のない法案を大量に強行採決したことなどを絶対に忘れてはいけません。

 選挙以外でも、とにかく言い訳と逃げの姿勢が目に付く安倍内閣。タカをくくっていたところ、慰安婦決議が米国で採択されて大慌てです。傑作なのが中山氏らが米紙に出した自己正当化文で、先に慰安婦問題で米国の怒りを静めようとした安倍発言を無視したようなものになっており、これが米国を憤慨させたようです。とはいっても、安倍氏は単にその場を取り繕っただけですから、中山氏のような意見が本音なのでしょうが。
 この問題、はっきり言って「慰安婦問題はなかった」と隠蔽を図るより、「問題はあったが、戦時中のことであるし、他国でも虐殺を含め様々な人権侵害行為があった。何が悪い」と開き直られる方がまだマシです。どちらにしても米国は怒るでしょうが、米国より日本国民にとって、前者と後者では雲泥の差です。
 最近の安倍姿勢を見る限り、どうやら安倍氏及び内閣は戦争によって発生した様々な行為を「過ちを犯した」ではなく、「やむを得なかった」でもなく、「存在しなかった」としたいようです。例えば沖縄戦問題でも、集団自決について「過ちだった」ともせず、「あの状況下では仕方なかった」ともせず、「軍による集団自決はなかった」として存在を闇に葬ろうとしています。生き証人が減る一方である現代、これは非常に効果的な手法です。
 また、安倍内閣で特徴的なのが「有識者会議」です。これは自分に近い人間でガチガチに固めた「第三者機関」をつくり、第三者が判断したと見せかけて自分の意見を通すための組織です。言うまでもありませんが、所詮はイエスマンのみを集めた会議であって、存在する意味すらありません。
 なぜこのような姑息な手段を用いるのか私には理解できませんが、憲法解釈の変更による集団的自衛権の許可など重要なことが次々に好き勝手に決められています。しかし、本当の有識者の多くは「集団的自衛権を使用したいなら、憲法改正で国民に意思を問うのが当然だ」と主張するでしょう。国民の多くはすでにこの組織の実態を見抜いているのに、未だになぜ「有識者」とやらをダシに使おうとするのか理解できません。

 有識者会議といえば、TBSと楽天の問題について。株主総会でTBSが楽天に快勝しました。私も楽天の横暴にはほとほとあきれており、これ自体は評価すべきことなのですが、問題はTBSの意味不明な買収防衛策です。
 買収者が現れた場合、その買収が適切であるかを第三者組織が判断、不適切であれば毒薬が溶け出す仕組みになっているのですが、問題はこの「第三者組織」です。毎日新聞の人間が入っているというだけで、すでに公平性に問題があります。要するに、この防衛策は安倍内閣の有識者会議と大して変わらないのです。
 今回の問題については楽天が排除されるべきなのですが、それでもTBSの方法は非常に疑問が大きいです。鉄盗人が犬にほえられて退散(言うまでもありませんがスティールとブルドックソース)したことは非常に愉快なのですが、こちらは愉快とも言っていられません。TBS方式が多くの企業で導入されるのは避けたいところです。
 その点、ブルドックソースの解決法は極めて妥当です。何といっても裁判でブルドック側が勝ったのが大きく、判決が防衛策にお墨付きを与えたものといえます。判例主義の概念からして、おそらくこの型の買収防衛策は法的に有効になると考えられますし、今後法律で定められるにしても、これに準じたものになるでしょう。今までは買収防衛策に法的な裏づけがなく、訴えられればひっくり返りかねない危うさがありましたが、これも解消されるでしょう。
 ただ、今後もしばらく泥沼の法廷劇が発生することは避けられない印象です。今回の判決では「株主の圧倒的賛成」「買収者に対する金銭の交付」などがブルドック勝訴の理由とされましたが、では特別決議ではない決議で防衛策が導入されたら。しかも賛否が拮抗したら。買収者に金銭が交付されないか、されたとしても少額なら。突き詰めるとキリがなく、そのたびに裁判が起こされることは避けられないのです。
 三角合併も解禁され、一部企業の業績が回復し、それでいて株価が低いとなれば、米国のハゲタカグリーンメーラーが日本を狙うのは当然です。グリーンメーラーは自己利益以外のことを考えませんから、自分の訴えを通すためなら裁判も辞さないでしょう。明確な基準が判例から読み取れるようになるまでは裁判が起こる可能性があると考えるべきです。

 技術は尊いものである。技術は生命の歴史そのものである。技術は唯一の真理である。技術は剣にもペンにも勝る。のですが、今回だけは「PHPのStAXのひどさを検証するブログ」になることをお許しください。技術を真っ向から100%非難することはしたくありませんが、PHPのStAXはそれを差し置いてもネタになります。興味本位で1度は使用されてみては。
 まずPHPのXMLWriterについては前回の通りです。エレメントにネームスペースを付加し、その子エレメントでも同じプレフィックス及びネームスペースURIを使用した場合、Javaなど常識的なパーサやライターではこうなります。
<y:Parent xmlns="http://www.yamicha.com/">
	<y:Child />
</y:Parent>
 ところが、PHPのXMLWriterではこうなります。
<y:Parent xmlns="http://www.yamicha.com/">
	<y:Child  xmlns="http://www.yamicha.com/" />
</y:Parent>
 あり得ません。とんでもない動作です。これでRSS 1.0でも書こうものなら、普通に書いた場合と比べてサイズが2倍以上になってしまう恐れが多分にあります。
 ではXMLReaderではどのような動作になるのか。結論から言えば、やはりあり得ません。ネームスペース周りの動作がとにかくひどすぎます。なお、PHP 5.1にて動作を確認しています。以降のバージョンでは修正されている可能性がありますし、修正されなければ困ります。なお、以下に示すXMLでは、可読性のためにインデントや改行を入れるなど、適時書式を変更しています。
 ではまずネームスペース以外の動作から。次のようなXMLを考えてみましょう。
<?xml version="1.0"?>
<Parent>
	<Child />
</Parent>
 見ての通り、ごく普通のノードです。
 検証用に次のPHPを作成します。
<?php
header("Content-type: text/plain");

$reader = new XMLReader();
$reader->open("filename.xml");

while($reader->read()){
 switch($reader->nodeType){
  case XMLReader::ELEMENT:
   print "<{$reader->name}";

   $empty = 0;
   if($reader->isEmptyElement)
    $empty = 1;

   if($reader->hasAttributes){
    while($reader->moveToNextAttribute()){
     print " {$reader->name}=\"{$reader->value}\"";
    }
   }

   if($empty){
    print " /";
   }
   print ">";
   break;
  case XMLReader::END_ELEMENT:
    print "</{$reader->name}>";
   break;
  case XMLReader::TEXT:
  case XMLReader::WHITESPACE:
   print $reader->value;
   break;
  case XMLReader::COMMENT:
   print "<!--{$reader->value}-->";
   break;
  case XMLReader::CDATA:
   print "<![CDATA[{$reader->value}]]>";
   break;
 }
}

$reader->close();
?>
 内容はおおむね見ての通りでしょう。これを実行した場合には、正しくXMLが生成されます。そこまでは良いのです。
 ではネームスペース対応にするにはどうすれば良いでしょうか。XMLReaderのプロパティには「name」「localName」「prefix」「namespaceURI」が用意されています。これを使って判別してやれば、さほど苦労せずにネームスペースが扱えそうです。実際、JavaのStAXでも(プロパティではなくメソッドですが)同じようにして使うことができました。
 しかし、そうは問屋が卸しません。PHPのXMLReader/Writerに対して信用取引は厳禁です(何のことやら)。正確には、問屋は卸してくれたものの、内容がメチャクチャで全部仕入れ戻ししなければならなかった、とでも言いましょうか。
 まず、タグにネームスペースが存在するのかをどのように判断するかが問題になります。ネームスペースにはデフォルト値を設定できるため、prefixプロパティではURIがあるのかないのか判断できません。やはりnamespaceURIプロパティを使うべきでしょうか。
 ではここで問題です。次のようなコードを書いたとして、
header("Content-type: text/plain");

$reader = new XMLReader();
$reader->open("xmlreader.xml");

while($reader->read()){
 switch($reader->nodeType){
  case XMLReader::ELEMENT:
   if($reader->namespaceURI)
    print "[element] {$reader->name} NSURI={$reader->namespaceURI}\n";
   else
    print "[element] {$reader->name}\n";

   if($reader->hasAttributes){
    while($reader->moveToNextAttribute()){
     if($reader->namespaceURI)
      print "[attribute] {$reader->name}={$reader->value} " . 
       "NSURI={$reader->namespaceURI}\n";
     else
      print "[attribute] {$reader->name}={$reader->value}\n";
    }
   }
   break;
 }
}

$reader->close();
 次のXMLをパースしました。
<?xml version="1.0"?>
<Parent xmlns="http://d.yamicha.com/default" 
	xmlns:y="http://yamicha.com/">
	<Child y:value="a" />
</Parent>
 さて、どのような結果になるでしょうか。
 以下が答えです。
[element] Parent NSURI=http://d.yamicha.com/
[attribute] xmlns=http://d.yamicha.com/ NSURI=http://www.w3.org/2000/xmlns/
[attribute] xmlns:y=http://yamicha.com/ NSURI=http://www.w3.org/2000/xmlns/
[element] Child NSURI=http://d.yamicha.com/
[attribute] y:value=a NSURI=http://yamicha.com/
 ネームスペース宣言をアトリビュート扱いしています。ネームスペースはXMLそのものの仕様には含まれていないため、解釈的にはこれで正しいのでしょうが、普通パーサがネームスペースをアトリビュート扱いするでしょうか。どうやらxmlnsはプレフィックスとみなされているらしく、このプレフィックスにはhttp://www.w3.org/2000/xmlns/というURIが割り当てられています。
 ところが、例えばxmlns:yならxmlnsをプレフィックス、yをアトリビュート名と解釈するくせに、デフォルト宣言(xmlns="URI")の場合はxmlnsがアトリビュート名(プレフィックス名なし)とみなされます。これは仕様的に大きく矛盾しています。しかもどちらの場合も(なぜか)ネームスペースURIが存在するとみなされ、そのURIは上記のものになるのです。そもそもXMLではアトリビュートにデフォルトネームスペースURIは適用されないはずですから、プレフィックスなしでURIを持つアトリビュートなど奇怪すぎます。
 これを逆手に取り、namespaceURIプロパティの値が「http://www.w3.org/2000/xmlns/」である場合のみネームスペースとして解釈する、といった手段もありますが、それにしても不可解すぎるこの動作。ついでに一応明記しておきますが、上記の方法でアトリビュートがネームスペース宣言であることを判別したとしても、「xmlns」はプレフィックスであったりアトリビュート名であったりします。そのため、プレフィックス名がない場合、もしくはアトリビュート名がxmlnsの場合はデフォルトネームスペース、そうでない場合は名前ありのネームスペースであると解釈することが必要です。
 もう1つ注意点を挙げておくなら、ネームスペース宣言はアトリビュートとみなされていますので、本当はアトリビュートが1つも存在しなくても、ネームスペース宣言さえあればhasAttributesはtrueになります。moveToNextAttribute()メソッドも有効になってしまいます。ゆえにhasAttributesプロパティを信じるのは極めて危険です。本当にアトリビュートがないことを確かめるには、hasAttributesがtrueの場合であっても、moveToNextAttribute()などを使ってアトリビュートを全部読んでみて、それらがすべてネームスペース宣言であることを確認しなければなりません。逆に言えば、hasAttributesがtrueだからといって、本当にアトリビュートがあるとは限りません。
 XMLReader、とりあえずXMLWriterよりは使えますが、これを使うなら素直にDOMを使った方が良いでしょう。といっても、PHPは今のところ(PEARやPECLを探せばありそうですが)標準でXPath 2.0やXQueryに対応していないため、XPath 1.0でちまちまノードを探さなければなりませんが、訳の分からないStAXモドキを使うよりずっとマシです。
 StAXの便利さは今さら説明するまでもありませんが、PHPの標準StAXがコレなのは非常に惜しいといえましょう。XMLReaderから読み込んでXMLWriterで書き込み、XMLの編集を行うことも一応できなくはありませんが、大変なXMLを出力されます。何を置いても、XMLWriterのひどさが特筆に価するといいましょうか。
 まずデフォルトURIを使う場合を考えます。通常なら「startElementNS("" , "NodeName" , "URI" , "value")」と書くところです(先頭の引数はプレフィックス)。ところが、どう見ても常識的なこの記述を行うと、何と「:NodeName」という訳の分からないノードを出力してくれます。そういうわけで、ここはネームスペースを使わないstartElementを使わなくてはなりませんが、これでは概念上ノードにURIが関連付けられていないことになります。それだというのに、XMLReaderではプレフィックスがなくてもデフォルトネームスペースURIを引っ張ってきてくれます。同種のライブラリのくせに、ReaderとWriterで挙動が全く違うのです。
 これをReaderからWriterに渡そうとすると、この挙動の調整は開発者の仕事になってしまうのです。具体的には、ネームスペースがあってもプレフィックスがない場合、XMLWriterのstartElementNSを使ってはならず、startElementを使わなければならないことになります。ただ、幸いというべきか、アトリビュートにはデフォルトネームスペースがないため、これを考慮する必要はありません。
 以下に実物を示します。ただし、DTD及びEntity、Document宣言については考慮していません(Document宣言は書き込み側で独自に設定することもありますし、DTDやEntityに関してはXMLで設定ファイルを書く場合などにはほとんど使いませんので、必要性は薄いでしょう。そもそもDTDはネームスペースに対応しないなど、レガシー要素が大きすぎます)。また、どうやらXMLWriterではCDataを書き込めないらしく、仕方がないのでテキストノードに変更して書き込んでいます。
$reader = new XMLReader();
$reader->open("filename.xml");

$writer = new XMLWriter("1.0");
$writer->openMemory();

while($reader->read()){
 switch($reader->nodeType){
  case XMLReader::ELEMENT:
   if($reader->prefix)
    $writer->startElementNS($reader->prefix , 
     $reader->localName , $reader->namespaceURI);
   else
    $writer->startElement($reader->localName);

   $empty = 0;
   if($reader->isEmptyElement)
    $empty = 1;

   if($reader->hasAttributes){
    while($reader->moveToNextAttribute()){
     if($reader->namespaceURI == "http://www.w3.org/2000/xmlns/")
      $writer->writeAttribute($reader->name , $reader->value);
     else if($reader->namespaceURI)
      $writer->writeAttributeNS($reader->prefix , 
       $reader->localName , $reader->namespaceURI , $reader->value);
     else
      $writer->writeAttribute($reader->localName , $reader->value);
    }
   }

   if($empty)
    $writer->endElement();

   break;
  case XMLReader::END_ELEMENT:
   $writer->endElement();
   break;
  case XMLReader::TEXT:
  case XMLReader::WHITESPACE:
  case XMLReader::CDATA:
   $writer->text($reader->value);
   break;
  case XMLReader::COMMENT:
   $writer->writeComment($reader->value);
   break;
 }
}

$reader->close();

print $writer->outputMemory();
 後はこのコードに手を加え、好き勝手に編集するだけです。
 しかし、実際のところこれは使い物になりません。それというのも、xmlnsをアトリビュートとみなしてしまう上、startElementNSではxmlns宣言を(問答無用で)行ってしまうため、
<c:Classes xmlns:c="http://yamicha.com/class" />
 このようなXMLをパースすると、xmlns:cが2つ(startElementNSによるxmlns:c宣言、及びアトリビュートによるxmlns:cの書き込み)になってしまい、エラーが発生します。
 ではどうすべきかといいますと、XMLの考え方を完全に捨て去り、ネームスペースの概念に背を向け、PHPのライブラリに最大限配慮してやるしかありません。つまり、プレフィックスをタグ名の一部と考えるのです。
 実際のところ、XMLネームスペースの考え方ではプレフィックスは単なるURIへのショートカットであり、それ自体は「URIの代替」以外の何の効果も持たないものであるはずなのですが、PHPのXMLReaderはxmlnsを(なぜか)アトリビュートとして扱ってしまい、XMLWriterのネームスペース管理は全く信用に値しません。こうしたことから、XMLのあるべき姿を捨て去らなければならないのです。正直言ってそこまでして使うほどの価値はないのではありますが、一応実装例を示します。
while($reader->read()){
 switch($reader->nodeType){
  case XMLReader::ELEMENT:
   $writer->startElement($reader->name);

   $empty = 0;
   if($reader->isEmptyElement)
    $empty = 1;

   if($reader->hasAttributes){
    while($reader->moveToNextAttribute()){
     $writer->writeAttribute($reader->name , $reader->value);
    }
   }

   if($empty)
    $writer->endElement();

   break;
  case XMLReader::END_ELEMENT:
   $writer->endElement();
   break;
  case XMLReader::TEXT:
  case XMLReader::WHITESPACE:
  case XMLReader::CDATA:
   $writer->text($reader->value);
   break;
  case XMLReader::COMMENT:
   $writer->writeComment($reader->value);
   break;
 }
}
 この通り、実装としてはシンプルなのですが、実際にこれを使ってXMLを編集する際には細心の注意を要します
 例えば、上記PHPコードを使い、Classesノードの子として「<c:Class />」ノードを登録するよう実装したとします。しかし、XML側のプレフィックスが変更されると、それだけでバグが発生します。また、startElementNSの使用は危ない(うっかりこれを使った場合、すでにXMLの同じエレメント内で同じプレフィックス名の宣言がされているとエラー)ため、XMLネームスペースはwriteAttributeによって登録することになりますが、これの管理も非常に面倒です。
 結論。ありきたりですが、PHPのXMLWriterとXMLReaderの使用はやめましょう。StAXはDOMより簡素で扱いやすい、はずなのですが、余計な苦労を背負うことになります。しかし、作者は一体何のためにこれをPHP標準ライブラリに含めたのでしょう。
カテゴリ [開発魔法][社会問題][経済・知的財産] [トラックバック 0][コメント 0]

鉄の盗人を撃退した犬
2007/06/25(Mon)20:57:45
 ブルドックソースの防衛策が株主総会で承認。やりました。何と80%以上の株主同意を得られたのですから、事実上の総意に近いものと考えても差し支えないでしょう。これは非常に素晴らしいことです。
 ライブドアがグリーンメーラー・村上ファンドにそそのかされ、ニッポン放送に対して攻撃を仕掛けてから、ここ数年で状況はめまぐるしく変わりました。ライブドアの没落も、村上ファンドの終焉も、そしてハゲタカグリーンメーラーの市場からの排除も、当時からそうなるであろうことを予想はしていたのですが、予想よりも速いテンポで進んでいるようです。
 スティールがグリーンメーラーであることは、これまでの態度を見れば明らかです。明星食品の株を買い占めて脅迫し、日清食品に高値で買い取らせたりと、とにかくあくどい行為を繰り返しています。しかし、グリーンメーラーの存在意義は「利益を上げている他業種に付け込んで、その利益をスポイルする」ことにあるのですから、あくどいのは当然というものです。
 本来、このような行為は禁じられるべきなのですが、法によってグリーンメーラーを完全に取り締まるのは困難です。グリーンメーラーは一見普通の取引者ですので、これを取り締まるのは夜間外出者をすべて取り締まるほど難しいことです。また、グリーンメーラーは抜け穴探しの達人ですから、何か規制を作っても即座に抜け道を探し出すことでしょう。
 しかし、私は村上ファンドの行為を見た時点で、いつしかグリーンメーラーが排除されることを確信しました。あのような行為を法が許したとしても、多くの国民が許すわけがありません。利益を上げている業種を狙い、その利益を根こそぎ自分のものにしたり、突然の攻撃によってステークホルダー(従業員と消費者を含む)に著しい不利益を与えたり、長期的に見て日本経済全体の足かせとなったりと、こうした輩をのさばらせておくのは害悪以外の何者でもありません。
 結果、多くの株主はグリーンメーラーを嫌い、従業員はグリーンメーラーの攻撃に怒り、グリーンメーラーの味方はいなくなります。また、攻撃対象となったA社の株を保有するB社があるとして、もし買収者が高値のTOBなどを提案してきた場合、B社がそれを拒むと株主から株主代表訴訟で訴えられる可能性がありますが、もしA社を攻撃している買収者がグリーンメーラーであるとしたらどうでしょうか。
 B社にとってA社が友好的な会社であり、取引先であったり業務提携先であったりする場合、B社は「A社がグリーンメーラーに買収されない方が会社の利益になる」と主張する可能性があります。それでも株主代表訴訟が起こされる恐れはありますが、株主の多くが買収者をロクでもない相手と認識していれば、この決定に異議は出ません。
 また、A社自身がB社に自社株を売却し、子会社入りする場合も同様です。グリーンメーラーがA社に買収を提案してきたとして、それがB社の買取額より高値であったとしても、A社がグリーンメーラーに身売りするわけがありません。また、ステークホルダーの多くはそれを認めないでしょう。
 こうしたことから、ハゲタカグリーンメーラーは必ず消え去る運命にあることが分かります。ブルドックソースが買収防衛策の導入を検討し、それが株主総会で認められるのも当然です。スティール側は裁判などで悪あがきをする予定のようですが、ブルドックソース従業員が買収に反対している上、株主の多くがスティールを支持しないことが明確になった以上、スティールにこれ以上の手出しは不可能でしょう。
 最近は少しずつ株主同意付きの買収防衛策を導入する企業が増えてきました。また、グリーンメーラーを時代の寵児とみなすかのような風潮はなくなり、グリーンメーラーの行為が適切に評価されるようになりました。スティールが日本市場から叩き出され、日本に居座るにしても細々とやるしかなくなり、他のグリーンメーラーも排除あるいは門前払いされるようになるのは時間の問題でしょう。

 今まで全く気づかなかったのですが、何とPHPにはStAXがあるらしいのです。「横のつながり」が薄いXMLを扱うに当たっては、確かにStAXはDOMよりも簡素で便利ではあります。
 PHPでもJavaでもオブジェクト指向マップ型のXML API名は「DOM」でしたが、PHPのStAXは「XMLReader」及び「XMLWriter」という名前になっています。しかし、ドキュメントで「プル型のXMLパーサ」と明記してある通り、中身は明らかにStAXと同等です。
 それでは適当なXMLを作ってみるとしましょうか。
header("Content-type: text/xml");

$stax = new XMLWriter();
$stax->openMemory();

$stax->startDocument("1.0");
$stax->startElement("Languages");

$stax->startElement("Language");
$stax->writeAttribute("id" , "1");
$stax->text("Perl");
$stax->endElement();

$stax->startElement("Language");
$stax->writeAttribute("id" , "2");
$stax->text("PHP");
$stax->endElement();

$stax->endElement();

print $stax->outputMemory();
 見ての通り、JavaのStAXとほとんど同じです。XMLReaderに関しては今回は省略しますが、ノード名など一部のデータをメソッドではなくプロパティから取得することを除けば、こちらもJavaとほぼ同じと考えて良いでしょう。結果は次の通りです。
<?xml version="1.0"?>
<Languages>
<Language id="1">Perl</Language>
<Language id="2">PHP</Language>
</Languages>
 startElement()には開始タグ名が必要ですが、endElement()には不要です。これもJavaのStAXと同様です。もしエレメントに子エレメントやテキストなどがなければ、自動的に省略形式(<Element />)のエレメントが作成されます。ただし、fullEndElement()メソッドを使用することで、明示的に閉じタグを作成することもできます。
 XMLReader、XMLWriterともに、当然ながらネームスペースも使用可能です。
header("Content-type: text/xml");

$stax = new XMLWriter();
$stax->openMemory();

$stax->startDocument("1.0");

$stax->startElementNS("y" , "NSElement" , "http://www.yamicha.com/");
$stax->endElement();

print $stax->outputMemory();
 言うまでもありませんが、結果はこうなります。
<?xml version="1.0" ?>
<y:NSElement xmlns:y="http://www.yamicha.com/" />
 ただ、ざっとドキュメントを見渡した限りでは、好きな場所でネームスペース宣言を行うメソッドは存在しないようです。子エレメントで大量にネームスペースを使う場合など、親エレメントでネームスペースを使えた方が良いことも多々あるのですが。
 そればかりか、ネームスペース周りの仕様が非常に美しくありません。例えば
header("Content-type: text/xml");

$y = "http://www.yamicha.com/";

$stax = new XMLWriter();
$stax->openMemory();

$stax->startDocument("1.0");

$stax->startElementNS("y" , "Parent" , $y);

$stax->startElementNS("y" , "Child1" , $y);
$stax->endElement();

$stax->startElementNS("y" , "Child2" , $y);
$stax->endElement();

$stax->startElementNS("y" , "Child3" , $y);
$stax->endElement();

$stax->endElement();

print $stax->outputMemory();
 このようなコードを書いたとしましょう。常識的に考えれば、次のようなXMLが生成されるべきです。
<?xml version="1.0"?>
<y:Parent xmlns:y="http://www.yamicha.com/">
<y:Child1 />
<y:Child2 />
<y:Child3 />
</y:Parent>
 ところが、実際に生成されるのは何とコレです。
<?xml version="1.0"?>
<y:Parent xmlns:y="http://www.yamicha.com/">
<y:Child1 xmlns:y="http://www.yamicha.com/"/>
<y:Child2 xmlns:y="http://www.yamicha.com/"/>
<y:Child3 xmlns:y="http://www.yamicha.com/"/>
</y:Parent>
 まさか私はバカにされているのでしょうか。RSS 1.0などではネームスペースを乱発しなければなりませんが、うっかりこれでRSSを生成しようとしたら、一体どうなってしまうのでしょうか。想像するだけでぞっとします。
 一応、ネームスペースを宣言すべき場所でstartElementNSを使ってネームスペースとプレフィックスを記述し、それ以後はstartElement("prefix:local")のように登録していけば、ネームスペースを使えないこともありませんが、これではネームスペースの概念に反しています。そればかりか、もしstartElementNS()を削除しなければならなくなれば、帳尻合わせが極めて大変ですし、ネームスペースのオーバーライドでも行おうものなら、プレフィックスの対応が相当に混乱することは見えています。
 この部分は要改善でしょう。少なくとも「親またはそれより上位で宣言されているネームスペースは、オーバーライドされない限り子で再宣言しない」「エレメントやアトリビュートでネームスペースを宣言せずとも、好きな場所でネームスペースを宣言できる」の2点は絶対に導入が必要な機能です。
 もう1つの問題点としては、既存のXMLの修正が非常にやりづらいことがあります。JavaのStAXでいうところのXMLEventが存在しないため、修正不要な部分ではXMLEventをリーダーから受け取ってそのままライターに渡すという方法が使えず、あらゆるタイプのノードに関する処理を自前で用意しなければなりません。
 このように、PHPのStAX APIはJavaのStAXと比べてかなり見劣りします。また、PHPのDOMと比べてもとにかく制限が多いのですが、StAX自体はなかなか魅力的な技術であるため、今後に期待するとしましょう。

 SQL番外(XQuery)編。ゲスト出演者がいれば、通常編を書いても良いのですが。

イリスのシェリー「・・・ですから、もうすぐドロシーが到着するころです」
魔道士イリアス「ドロシーっていうと・・・あの人ね」
イリスのシェリー「ところでイリアスさん、すみませんがアイスピックか何かを取っていただけませんか?」
魔道士イリアス「アイスピック・・・はないけど、これは使えないかしら」
イリスのシェリー「イリアスさん、それは小剣ではありませんか・・・」
魔道士イリアス「小剣じゃダメなの?」
イリスのシェリー「いえ、何とかならないこともありませんが・・・。それにしても、なかなか装飾が美しい剣ですね」
魔道士イリアス「お目が高いわね、シェリー。これが名剣ネイピアよ」
イリスのシェリー「ネイピア?」
魔道士イリアス「私も良く分からないんだけど、もともとは人の名前らしいわね。でも、実際にこれを考えた人は別人とか・・・」
数学者ドロシー「ネイピアはオイラが考えたものですよ」
魔道士イリアス「へー、あなたが考えたの?さすがねえ・・・」
数学者ドロシー「イリアスさん、これは私ではなくオイラが・・・」
魔道士イリアス「だから、あなたが考えたのよね?」
騎士サーラ「イリアスさん、数学者オイラーのことです」
魔道士イリアス「ああ、この前言ってたオイラーね」
イリスのシェリー「それで、ネイピアとは一体何なのですか?」
騎士サーラ「ネイピア数といいますのは、すなわち・・・ですから、つまり・・・」
イリスのシェリー「あの、サーラさん、良く分からないのですが・・・」
数学者ドロシー「サーラさん、シェリはどうも数学的なことが苦手なのです。かくいう私も経済なんかは苦手だけど・・・」
魔道士イリアス「で、どうやったら使えるのよ、そのネイピアって」
騎士サーラ「EXPです」
魔道士イリアス「EXP?・・・何よ、この意味不明なの」
イリスのシェリー「脈略のない数列にしか見えませんが・・・」
数学者ドロシー「シェリもエコノミばかりじゃなくて、たまには数学でもやったら?」
魔道士イリアス「サーラ、この数値ってどういう意味なの?」
騎士サーラ「色々と意味はあるのですが、一口に説明するのは難しいですね」
魔道士イリアス「何か難しそうね。REGEXPなら私でも使えるんだけど・・・」

 SQLでは、EXPは「EXP(1)」で、REGEXPは「REGEXP」で使うことができます。「SELECT EXP(1) REGEXP '[0-9].[0-9]+'」などと打ってみるのもお茶目で良いのではないでしょうか。

数学者ドロシー「イリアスさん、この前クエリというものを見せていただきましたが・・・」
魔道士イリアス「クエリ?SELECTとかINSERTとか?」
数学者ドロシー「はい。それで虫食い算や覆面算を解くことは可能でしょうか?」
魔道士イリアス「言うまでもなく、解けるわね」
数学者ドロシー「では、例えばこのようなものは・・・」
 SEND
+MORE
MONEY
魔道士イリアス「ああ、以前にやったわよ、これ。古典的な覆面算の名作らしいわね。じゃ、早速クエリを・・・。
あれ?シェリー、ログインできないんだけど、一体どうなってるの?」
イリスのシェリー「あの、イリアスさん。現在イリスのSQLサーバーは止まっておりまして・・・。数時間中に復旧する見込みです」
魔道士イリアス「えーっ!?」
騎士サーラ「SQLが使えないのでは、やむを得ませんね・・・」
魔道士イリアス「何とかならないの?」
騎士サーラ「残念ながら、この媒体にはSQLクライアントのみが導入されていて、サーバーは入っておりません。また、各種開発環境も入っていませんので、使えるとしてもせいぜいXQueryが限度でしょう」
魔道士イリアス「クエリ?何だ、クエリが使えるのね。サーラ、それを先に言ってよ」
騎士サーラ「しかしイリアスさん、クエリはクエリでもXQueryはSQLではなく・・・」
魔道士イリアス「細かいことは後でいいわ。さあ、やるわよ!やっぱり開発魔道士とクエリは切っても切れない関係ね」
騎士サーラ「・・・・・・」

 クエリはクエリでも、今度はXQueryによって問題を解かなければなりません。果たしてそのようなことができるのでしょうか。

模範解答
 XQueryでCROSS JOINもどきのことをするには、どうしてもfor文を使うことになります。XQueryのfor文といえばwhere節です。これらを使ってスマートに問題を解いてしまいましょう。
 覆面算では、あらゆる数値の上1ケタの値は必ず0以外になります。また、2つの値を足し合わせて答えを出す場合、答えの値が繰り上がっていれば、その繰り上がった部分の数値は必ず1です。同じ文字の部分には同じ数字が入り、異なる文字同士が同じ数字になることはありません。これらを踏まえてクエリを作るとしましょう。
 まず「異なる文字同士が同じ数字になることはない」点については、シーケンスとの比較によって実装するのが簡単でしょう。シーケンスとの比較とは、例えば「($a,$b,$c) = $d」といった式のことです。この場合、$a,$b,$cの中に1つでも$dと同じものが含まれていれば、この式はtrueとみなされます。
 それでは、上記と正反対である「異なる文字が同じ数字にならない」ことを実装するにはどうすれば良いのでしょうか。普通に考えれば「($a,$b,$c) != $d」ですが、実際に試してみて誤りであることが分かりました。XPathにおいては、演算子が=の場合は「いずれかに比較対象の値を含む」のくせに、!=の場合は「いずれかに比較対象と異なる値を含む」なのです。すなわち「not(($a,$b,$c) = $d)」とする必要があります。
 これらを踏まえると、次のようなクエリを作ることができます。
declare variable $num := (0,1,2,3,4,5,6,7,8,9);
for $s in $num where $s != 0 return 
for $e in $num where not($s = $e) return 
for $n in $num where not(($s,$e) = $n) return 
for $d in $num where not(($s,$e,$n) = $d) return 
for $m in $num where not(($s,$e,$n,$d) = $m) and $m = 1 return 
for $o in $num where not(($s,$e,$n,$d,$m) = $o) return 
for $r in $num where not(($s,$e,$n,$d,$m,$o) = $r) return 
for $y in $num where not(($s,$e,$n,$d,$m,$o,$r) = $y) and 
($s * 1000 + $e * 100 + $n * 10 + $d) + 
($m * 1000 + $o * 100 + $r * 10 + $e) = 
($m * 10000 + $o * 1000 + $n * 100 + $e * 10 + $y)
return concat(($s * 1000 + $e * 100 + $n * 10 + $d) , '+' ,  
($m * 1000 + $o * 100 + $r * 10 + $e) , '=' ,  
($m * 10000 + $o * 1000 + $n * 100 + $e * 10 + $y))
 このクエリの実行結果は次の通りです。
9567+1085=10652
 すなわち、覆面算の答えは
 9567
+1085
10652
 であることが分かります。

数学者ドロシー「これもSQLクエリ・・・なのですか?」
騎士サーラ「いえ、これはXQueryといいまして、XPath 2.0から派生したものです。もともとはツリー型文書から必要なデータを取得するためのものなのですが、SQL経験者のためにSQLに似せた言語形態が定められており、応用次第で様々なことができるのです」
数学者ドロシー「では、SQLとは全く別物なのですか・・・」
騎士サーラ「しかしイリアスさん、XQueryなどいつの間に習得されたのですか?」
魔道士イリアス「ま、何となくね。私としては、仕様がガチガチに定められてるより、色々応用が効く言語が好きだから、習得してみたくなったのよ」
騎士サーラ「実際に打ってみて、いかがでしょうか?」
魔道士イリアス「使えるには使えるんだけど、さすがにSQLには負けるわね。テーブル作らなくていいのが楽といえば楽だけど、結局シーケンスは作らなきゃならないし・・・」
数学者ドロシー「しかし、本当にこのような記述から答えが出てくるのですか?まさに魔法ですね・・・。これがプログラムなのですか?」
魔道士イリアス「プログラムというより・・・XQueryやSQLクエリは1つの式と考えた方が良いわね」
数学者ドロシー「見た目から、何となく数学の式であることは分かるのですが・・・。私には理解できません・・・」
魔道士イリアス「そりゃそうよ。式は式でも、式言語は数学分野じゃないからね」
数学者ドロシー「・・・サーラさん、先ほどから気になっていたのですが、あなたもこのXQueryというものを習得していらっしゃるのですか?」
騎士サーラ「ええ、一通りは・・・」
数学者ドロシー「さすがは師団のスタですね!シェリがベタぼめするのも分かります」
騎士サーラ「シェリーさん、一体何を大げさにおっしゃったのでしょう・・・」
数学者ドロシー「大げさなどとは、とんでもありません。掛け値なしに師団のスーパ・ヒーロですよ」
騎士サーラ「しかし・・・」
数学者ドロシー「ヒロインはイリアスさんでしょうか。お似合いですよ」
魔道士イリアス「・・・シェリー、それってどうなのよ!」
イリスのシェリー「どう・・・と私に言われましても・・・」

 XQueryはこれでなかなか使えるのです。
カテゴリ [開発魔法][社会問題][経済・知的財産] [トラックバック 0][コメント 0]

見送り千両
2007/06/14(Thu)18:58:07
 まずはホットニュースを。
 内閣府の審議会で個人情報保護法の改正が見送られることになりました。安倍内閣の決定としては唯一評価できるかもしれません。マスコミの再三にわたる偏ったキャンペーン報道、具体的には個人情報保護法の欠点ばかりをひたすら探して非難したり、同法に批判的な見解を示す人のコメントのみを取って記載するなどの報道に加え、参院選の点数稼ぎのために政府がマスコミにおもねる危険性もありましたが、今回はとりあえず回避されました。
 既得権益を侵されると怒るのは族議員も談合業者もマスコミも同じのようで、マスコミの同法に対する攻撃にはすさまじいものがあります。結果として国民が「個人情報保護法は悪」という考えを刷り込まれてしまい、「個人情報保護法を緩和・廃止するのが善」とされることにより、政府が同法の緩和を言い出さないとも限らない状況でしたので、正直なところほっとしています。
 確かに過剰反応は問題です。例えば大事故が発生した際、病院が警察に情報を提供しないなどというのは問題です。しかし、これは同法の趣旨が病院側に正しく理解されていなかったのが問題なのであり、「警察の要請を拒む必要はない」ことについての周知を図れば足ります。同法では警察の要請に対しては開示可能とされているのですから、問題は法の趣旨が誤解されていることであって、法律自体に手を加えなければならない点はありません。
 しかし、マスコミの不用意な取材によって被害者にダメージを与えたり、場合によっては災害救助活動そのものを妨害されかねないことを考えれば、被害者の情報を警察に開示することがあっても、マスコミに開示する際には本人同意が必要なのは当然です。他人の敷地内にまで入り込んだり、親族や友人にまで攻撃をかけたり、玄関先にタバコや空き缶を撒き散らしていくような連中に取材されても良いという覚悟がある人のみが情報公開に同意すれば良いのです。マスコミは「自主規制」を強調していますが、その「自主規制」に効果があるのかを判断するのは国民であり取材される人間であって、マスコミが自分で判断するものではありません。マスコミが本当に自主規制で節度ある取材を行っているのなら、多くの人が情報公開に同意するでしょう。
 連絡網が作れないなどの問題についても、おおむね甘受すべき不便さの範囲内でしょう。クラスには数十人の人間がいて、そのうち1人でも情報を漏らせば全員分の情報があっという間に業者の手に渡る現実があります。最近は電話番号を知らせずに電話を回すサービスを提供している電話会社もありますので、そうしたサービスの利用を検討するなど、連絡網の代替手段を検討するのが筋です。
 さらには、「1人暮らしの老人の孤独死・災害死を防止する活動があるのに、その対象の人が個人情報提供を拒否すると、防止活動団体に情報を渡せない。本人同意なしで渡せるようにすべき」という寝言を言い出すマスコミまで存在するほどです。本人はそのようなサービスを受けたくないから拒否しているのであって、それを受けたい人は拒否などしません。何か事情があるのかもしれませんし、実は近くに頼れる人がいるのかもしれません。果てはこうした活動以外についても、「公共の利益にかなう」の一言でなし崩し的に個人情報漏えいが認められてしまう危険があります。このような同意なし提供は絶対に認められてはいけませんし、これを例に出して個人情報保護法を批判するマスコミの方が批判されるべきです。
 また、個人情報保護を盾に、処分された役人の情報公開を拒む自治体や省庁も存在するようですが、これは個人情報保護法以前の問題です。そもそも個人情報保護法の対象になるのでしょうか。仮に対象となる、あるいは灰色の場合があるとしても、現存職員及び就職者に「私が違反行為で処分されたら、個人情報を公表されても異存ありません」という念書を書かせれば足りるでしょう(個人情報保護法は「本人の同意なき」個人情報公開を禁じるため)。逆に、仮に個人情報が廃止されたとしても、彼らの体質が変わるでしょうか。また何か別の理由をつけてくるのがオチでしょう。ともかく、こうした役人連中の保身がマスコミの個人情報保護法批判に利用されていることは否めません。
 個人情報保護法批判の多くは「過剰反応」に対するもので、正常に運用されている限りは当てはまらないものがほとんどです。むしろ、自分の個人情報が業者などの間で好き勝手に管理されていたのを自分の手に取り戻し、多くの人や企業に個人情報に対する意識の向上をもたらした点を大いに評価すべきでしょう。
 ひとまず改正が見送りになったとはいえ、今後ともマスコミのキャンペーンは続くと考えられますが、個人情報保護法は下手に緩和すべきではありません。議員やその他の連中が「個人情報など大したものではない」「住民基本台帳の情報は住所、氏名、生年月日、性別の4つだけだ」「お前の個人情報など誰が欲しがるのだ」と言い張り、何の対応もしなかった挙句、住民基本台帳を使った強制わいせつ事件が起こったことを忘れてはいけません。防げたはずの事件を防がなかったのは議員連中の怠慢で、強い憤りを覚えます。もう同じことを繰り返すわけにはいきません。

 今度ばかりはお得意の法令無視・迂回も通用せず、悪の枢軸であるとみられる折口氏が大批判を浴びた挙句、コムスンはおおむね分割譲渡の手段しかなくなったようですが、インチキ企業グッドウィルについて。
 コムスン問題で立場がまずいと判断したのか、折口氏は「派遣給与200円ピンハネ」の返金を口にしたのですが、何とグッドウィルは「返金には応じない」との姿勢。やはりグッドウィルはこのような企業なのでしょう。折口氏がとりあえず批判をかわすためにインチキを言ったのであれば詐欺も同然ですし、仮に折口氏が独断で発言を行い、グッドウィルとしては寝耳に水という状況であったとしても、記者会見の場で明言するというのはそれだけ重い行為です。グッドウィルに体質を変える気があるのなら、返金に応じなければなりません。それをしない以上は体質を変える気がないのでしょう。
 派遣には不透明な処理が横行しており、また派遣自体が少し前まで厳しく制限されていた麻薬・毒薬のようなものです。安易な規制緩和のツケがここへ来て回ってきたのでしょう。派遣業に対する規制を少しずつ強めていったり、グッドウィルや旧クリスタルのような悪徳を許さないよう、何らかの法整備を行うことが行政の責務です。
 次にスティール問題。明星食品などに対する作戦成功で調子に乗ったのか、ブルドックソースなど様々な企業をも荒らし始めました。スティールとは「鉄鋼」の意味らしいのですが、どう考えても「盗む」にしか見えません。最近は業績の良い企業も増えてきたようですが、そうした企業を脅してタカって利益を吸い上げてやろうというのがこうしたファンドの戦略なのです。
 そして極めつけは、スティールの共同創設者の「日本の事前警告型買収防止策は世界最悪」発言。世界最悪なのはまじめな企業にタカるハゲタカファンドどもです。実際、日本は株式市場の制限が非常にゆるく、しかも諸外国に比べて法整備も立ち遅れ、買収防止策も本当に有効なのか未だに定まっておらず、犯罪を犯しても軽い罪で済むという、まさにハゲタカの楽園です。さらには三角合併も解禁されました。外国資本が悪いとは言いませんが、国内外のグリーンメーラーどもにまともな企業が根こそぎ支配されることだけは御免です。
 まず犯罪に関しては、当然ながら厳罰化を検討すべきでしょう。ライブドア問題で少々厳罰化されたようではありますが、どこまで効果があるかは疑問です。振り込め詐欺では懲役数年の実刑が出た例があるのに、それより大規模な詐欺を行った堀江被告に2年6月(地裁判決)というのは軽すぎ、バランスを欠いています。やったことはニセ札作り(最高刑無期懲役)と同等以上にもかかわらず、重い罪を科すことはできないのです。
 無論、「グリーンメーラー天国」を改善すべきも言うまでもありません。グリーンメールは多くの場合、対象となった企業に良い影響を与えません。こうしたことから、グリーンメーラーの暗躍を阻止するのは非常に重要です。「企業に緊張感をもたらした」として村上ファンドを評価する声に対しては、検察が「泥棒が出たから家にカギをかけるようになったとして泥棒をたたえるようなもの」という名言を残していますが、その通りです。グリーンメール行為がやりづらくなるようなルール改正を行うべきでしょう。
 ただし、法改正だけでは十分な効果は見込めません。グリーンメーラーは法の迂回を専門業としているため、抜け穴を探されるばかりです。国民の多くが「グリーンメーラーは企業価値を低下させ、日本全体に迷惑をかけるものである」という意識を持てば、株主はグリーンメーラーを支持しなくなり、多くの関係企業もグリーンメーラーより被害社を支援するようになり、グリーンメーラーは衰退するしかなくなります。法改正も重要ですが、意識改革はそれ以上に重要です。
 実際、不完全な部分はありますが、こうした意識は着実に根付いてきています。スティールとブルドックを例に取れば、ブルドックの社員はそっぽを向いており、取引先9社もスティールに反対しています。もしスティールがまっとうな会社であれば、ここまで多くの反対は出ないでしょう。これは明星へのグリーンメールなど一連の問題で信頼を失ったためと考えることができます。
 村上ファンドの例では、日清紡による新日本無線の友好的買収に同ファンドが高値で割り込んだは良いものの、新日本無線は「日清紡の方が企業価値が高まる」として日清紡を売却先に選択しました。村上ファンドの所業を考えれば、当然の結論でしょう。
 こうした動きが積み重なれば、結果としてファンドが敵対的買収を仕掛けようとしても応じる株主・取引先が少なくなったり、従業員や取引先に大ブーイングを受けたり、企業買収・売却の際にファンドがより良い条件で横槍を入れてきても応じてもらえなかったり、そのことに対して株主代表訴訟が提起されなかったり(多くの株主が「高値でファンドに売るより少々安値でも今の売却先に売る方が良い」と判断)します。そうすればファンドは自然に消滅するしかなくなります。
 この分ならスティールも衰退は近い、と考えたいところですが、どうなりますやら。

 苦節(?>[1-9])[0-9]+日。ようやくスポットライトのテスト実装が完成しました。atan2とhypotは最強の魔法です。余談ですが、JavaのMath.atan2とExcelのATAN2は引数の順番が違ったりします。具体的には、三角関数の角度は右側を0度として反時計回りに数えるのですが、
問:右2センチ、上1センチの部分にある点の角度を求めよ

答(Excel)
=DEGREES(ATAN2(2 , 1))

答(Java)
Math.atan2(1 , 2) * 180 / Math.PI;

= 26.565...
 このように、Excelではx,yの順番で指定するのですが、Javaではsin,cosの順番で指定します。座標を表す際はx,y(,z)の順番が普通ですから、座標という意味ではExcelの方が自然な引数順になっています。しかし、三角関数は通常sin,cosの順番になりますから、三角関数という意味ではJavaの方が自然な順番です。個人的には、三角関数をsin,cosではなくcos,sinにすれば万事解決では、と考えるのですが。「コサイン・サイン・タンジェント」です。しかし実際、三角関数をどのように習うのかは知りませんので、何とも言えませんが。
 これまた余談ですが、atan2にはひたすらお世話になっています。atan2のあまりの有力さに、asinもacosもその地位を追われています。いちいち「asin(y / hypot(x , y))」とは書きたくありませんし。しかし、atan2などというアークタンジェントの名を冠するものを頻繁に使っていながら、考えてみればタンジェントを使ったことはほとんどないのです。それ自体は単なる割り算ですし、それが普通でしょうか。
 後はhypot、これにも非常に助けられました。ピタゴラスの功績は大きいです。三角関数を扱うのであれば、atan2とhypotは必修です。ちなみにJava 1.1ではMath.hypot()が存在しません。メソッドの手作りを余儀なくされます。しかし、それよりひどいのがExcelです。毎回使うたびに「=SQRT(A1^2+B1^2)」、3Dなら「=SQRT(SQRT(A1^2+B1^2)^2+C1^2)」としなければならないため、非常に面倒です。
 実際にはまだ色々検証が必要と考えられますが、スポットライトの図を。


 上空からのスポットライトの図。これだけではポイント光源と見分けがつきませんが、照射方向が決まっているため浮遊している三角形には影響がないということで。光の広さは45度、ファイ要素とシータ要素(照射中心点からの減耗がない範囲)が双方11.25度、カラーは黄色に設定してあります。角度が正しく認識されているかは怪しいですが、たぶん大丈夫でしょう。

 使ってみて分かりましたが、スポットライトは案外使い方が難しいです。
 懐中電灯をイメージしていただければ分かりやすいのですが、光の近くに照射点がある場合、確かに光は強くなるのですが、範囲が非常に狭くなります。本当に照明があるのか分からないほどに。しかし、光の位置を少々離してみると、今度は確かに範囲は大きくなるのですが、減耗がかかりすぎます。しかも「光の位置〜照射点」の減耗に加えて「照射点〜効果位置」までの減耗もあるため(シータ〜ファイ要素内に効果位置がある場合を除く)、本当につつましい光になります。本当に照明があるのか分からないほどに。言うまでもありませんが、解決法は「光からの距離を長く取り、光の射程も長くする」ことです。
 舞台照明としてはスポットライトが良く使われますが、これは相当射程が長いのではないでしょうか。舞台に届くまでに光が減耗しきってしまっては意味がありませんので。


 先の画像では分かりづらいため、右側から左へのスポットライトの図。ライトの光は上空を平行に進むのですが、光の範囲は円すい型に拡大していくため、このような照らされ方になります。不自然な見た目の通り、効果を確かめるために少々極端な設定にしてあります。光の角度全体をファイ要素と同等のシータ要素にしている上、光の強さは標準の32倍(当社比)。これで光の当たる部分も一目瞭然です。スポットライトは円すい型ですから、円すいの断面のような形をしています。

 後は実際に動かせるサンプルのリリースですか。実装中にトラブルが起こりそうで恐ろしいですが、とりあえず作成に着手しますので、どうか気長にお待ちください。

 XPath 2.0。何やら今年1月にW3Cから出されたようです。W3Cが何を勧告しようが興味はありませんが、XPath 2.0自体は面白そうですので、試してみることにしました。
 XPath 2.0は今のところJavaの標準実装には存在しませんし、PHPにも存在しないようです。しかし、世の中というのは広いもので、XPath 2.0に対応したJARライブラリがすでに作られています。Saxonだそうです。この単語、一体どういう意味なのでしょうか。皆様、axisは「アキス」、gotoは「ゴートー」と読みましょう。
 これをダウンロードし、-cpまたは環境変数でクラスパスを通すなり、AppServerなりTomcatなりのlibに投げ込むなりして使える状態にしたら、後はXPathFactoryを生成し、XPathを生成して使うだけです。生成手順は次の通り。
XPath xpath = new net.sf.saxon.xpath.XPathFactoryImpl().newXPath();
 標準APIのXPathFactoryはabstractのため、newInstance()でファクトリを生成しなければならないのですが、SaxonのXPathFactoryImplは実体クラスであるため、そのまま生成して使うことができてしまいます。ちなみに、XPathFactory.newInstance()で生成すると標準APIのファクトリインスタンスが取得されてしまい、XPath 2.0を処理できないのでご注意を。
 さて、XPath 2.0では概念が一新され、「ツリー」ではなく「シーケンス」をベースとした処理になっているそうです。概念はどうでも良いですから機能は確かめてみなくては。まずシーケンスとは、ノードのリストであったり、データのリストであったりします。配列のようなものと考えるべきでしょうか。シーケンスはカッコでくくって自作できます。ですから、次のようなXPath式は認められます。
(1 , 3 , 5)[2]
 XPathの要素数は1から始まるため、上記XPathは「3」を返します。シーケンスには整数の他、文字列(シングルクォートでくくる)や小数点も使用できます。もちろんノードも要素の1つとなります。
 もはや式言語と表現するには語弊が出るほど機能が追加されているそうですので、とにかく色々試してみなければ。そこで作成したのが以下のJSPです。
<%@page import="java.io.* , net.sf.saxon.xpath.* , 
javax.xml.xpath.* , javax.xml.namespace.QName , 
static javax.xml.stream.XMLStreamConstants.* , 
javax.xml.transform.* , javax.xml.transform.stream.* , 
javax.annotation.Resource , javax.xml.parsers.* , org.w3c.dom.* , 
javax.xml.transform.dom.* , org.xml.sax.SAXException" 
contentType="text/html;charset=Shift_JIS" %>

<html>
<head>
<title>XPath 2.0</title>
</head>
<body>

<b>XPath 2.0</b>

<%
request.setCharacterEncoding("Shift_JIS");

String xpath = request.getParameter("xpath");

if(xpath != null){
	out.println("<br><br>入力された XPath:<br>" + 
		xpath + "<br><br>");
	out.println("処理結果:<br>");
	try{
		DocumentBuilderFactory dbf = 
			DocumentBuilderFactory.newInstance();
		DocumentBuilder db = dbf.newDocumentBuilder();

		Document d = db.parse("webapps\\ROOT\\xpath2.xml");

		// XPath
		XPath xp = new net.sf.saxon.xpath.XPathFactoryImpl().newXPath();
		out.println(xp.evaluate(xpath , d));
	}catch(Exception e){
		out.println(e);
	}
}
%>

<form method="POST" action="?">
<textarea name="xpath" cols="60" rows="5"></textarea><br>
<input type="submit" value="XPath 処理">
</form>

</body>
</html>

// xpath2.xml
<?xml version="1.0" encoding="Shift_JIS" ?>
<Characters>
 <Character id="1">
  <Name>イリアス</Name>
  <Equipments>
   <Weapon>ネイピア</Weapon>
   <Shield>マナ・プレート</Shield>
   <Other>イリス書房 ネームスペース概論</Other>
  </Equipments>
 </Character>
 <Character id="2">
  <Name>サーラ</Name>
  <Equipments>
   <Other>The Java EE Tutorial</Other>
   <Other>XPath 2.0 Recommendation Document</Other>
   <Other>MySQL Reference Manual</Other>
  </Equipments>
 </Character>
 <Character id="3">
  <Name>シェリー</Name>
  <Equipments>
   <Weapon>ワリキュールランス</Weapon>
   <Other>スパークリング</Other>
  </Equipments>
 </Character>
</Characters>
 プログラム自体は短いですが、これでXPathを手軽に試すことができます。
 ではまず1.0式の階層ツリーから。
/Characters/Character[./@id=2]/Name

サーラ
 ここまでは1.0でも可能でした。しかし、2.0ではifやらeveryやら良く分からないものが大量に追加されています。個人的に「IF〜THEN〜ELSE」型の(文字ベースの)指定は大嫌いなのですが、ぜいたくを言っても仕方ありません。
 まずはforから。C++やJavaのforといえばループですが、XPathにおいては「シーケンスをループし、結果をシーケンスとして返す」ものです。
(for $value in ('Java' , 'Persistence' , 'API') 
return substring($value , 1 , 1))[2]

P
 このプログラムでは、まずカッコ内のシーケンスがループ処理されます。substringで最初の文字のみを切り出して返しますので、結果は('J' , 'P' , 'A')のシーケンスになります。その後で[2]を使ってデータを取り出しているため、このシーケンスの「P」が返ることになります。
 データを返す必要がなければ返さなくても構いませんし、シーケンスとして返すことで1要素から2つ以上のデータを返すこともできます。これはif文と組み合わせるとなかなか面白いのではないでしょうか。
 そんなこんなのif文ですが、VisualBasicライクです。よりにもよって。勘弁して欲しいです。
if (1 = 1) then 'true' else if(2 = 2) then 'true' else 'false'

true
 if〜else if〜else文です。言うまでもありませんが、else ifは任意です。それでは組み合わせてみましょうか。シーケンスは0個のデータ(空のカッコ)を扱うことができ、またreturnは複数のデータを含むシーケンスを返せますので、それも試してみましょう。
// 偶数の値のみを残し、その平均値を求める
avg(for $value in (1 , 2 , 3 , 4 , 5) 
return if($value mod 2 = 0) then $value else ())

3

// 値を2つに増殖し、その合計数を求める
sum(for $value in (1 , 2 , 3 , 4 , 5) return ($value , $value))

30
 それでは、こうした式をXMLに適用してみます。
 まずは「名前の文字数の合計」を求める例から。
sum(for $node in (/Characters/Character) return string-length($node/Name))

11
 この通り。$nodeはCharacterノードですので、$node/Nameと記述することで/Characters/Character/Nameにアクセスすることができます。言うまでもありませんが、Equipmentsなど他のノードにアクセスしたり、アトリビュートを取得してみたり、親階層に戻ったりすることもできます。
 こうしたものを組み合わせれば、かなり色々な式の作成が可能でしょう。自由度ではSQLに一歩劣る印象ですが、データベースと構造型の問い合わせでは制限が違うのは当然ですし、実際問題としてSQLクラスの表現力があればほとんど何でも可能です。
// 一番長い装備品
for $value in (/Characters/Character/Equipments/*) 
return if(string-length($value) = 
max(for $node in (/Characters/Character/Equipments/*) 
return string-length($node)) ) then $value else ()

XPath 2.0 Recommendation Document
 しかし、XSLTでXPathを使用するのであればともかく、JavaなりPHPなりの言語からXPathを使用するなら、無理に複雑怪奇なXPathを組むより言語側で処理した方がスマートでしょう。SQLの複雑怪奇なクエリについては、おそらく言語側で処理するより高パフォーマンスなSQL側で処理させることができる(さらに場合によってはトランザクションを適用したり、プリペアドステートメントを使って処理を軽減したり)というメリットがありますが、XPathは基本的に言語側のライブラリで行うものですから、言語側で処理しても大差はありません。とはいえ、XPathなら簡単でも言語側の実装は困難な式もあると考えられますから、状況次第でしょうか。
 SQLといえば、forの他にletが使えたり、for及びletの補助としてwhere、order byなどのSQLでおなじみの節も使えるそうですが、これはXQueryの仕様(XPath 2.0はXQueryのサブセット扱い)で定められているらしく、今回は使うことができませんでした。
 もう1つ、忘れてはいけないのがeveryとsome文です。
every $value in (1 , 1) satisfies $value = 1

true
 every及びsomeの構文はforと似ており、「every 変数名 in シーケンス」となります。ただし、returnではなくsatisfies節を使用し、ここには条件式を記述します。everyの場合はシーケンスのすべてが条件に当てはまる場合にのみ、someの場合は1つでも当てはまればtrueを返します。上記のXPath式においては、シーケンスは「(1 , 1)」であり、条件式が「$value = 1」であるため、trueとなります。仮にシーケンスが「(1 , 2)」であれば、2つ目の要素が条件式「$value = 1」に一致しなくなるため、falseを返すことになります。ただしeveryではなくsomeを使えばtrueを返してくれます。
 おそらくサブクエリ使いの方ならピンと来るでしょうが、これはSQLのANY及びALLとほとんど同じです。ANY及びSOMEに当たるのがsome、ALLに当たるのがeveryです。しかし、せっかく同等の機能がすでに存在するのですから、命令名をSQLのものに統一してくれれば良いものを。ALLをeveryとした理由は分かりませんが、ANYをsomeにしたのは「NOT ANY」問題を回避するためでしょう(SQLでnot equal演算子!=を使い「a != ANY (subquery b)」と記述したら、プログラム上は「bの中にaと異なるものが1つでもある場合」という意味になりますが、英文法では「aと同様のbは一切存在しない」という意味になります。この混乱を避けるためだけに、ANYと全く同じ効果を持つSOMEが用意されています)。
 初めて触れる新文法でも、サブクエリと同じであると考えれば簡単なものです。
// 全員が武器を持っているか
if(every $node in /Characters/Character 
satisfies $node/Equipments/Weapon) then 'yes' else 'no'

no

// 武器を持っている者が1人でも存在するか
if(some $node in /Characters/Character 
satisfies $node/Equipments/Weapon) then 'yes' else 'no'

yes

// 全員が2つ以上の装備品を身に着けているか
if(every $node in /Characters/Character/Equipments 
satisfies count($node/*) >= 2) then 'yes' else 'no'

yes

// SQL なら NOT ANY になってしまう(SOME を使う方が良い)例
// 「ネイピア」以外の武器を持つ者が1人でも存在する場合
if(some $weapon in /Characters/Character/Equipments/Weapon 
satisfies $weapon != 'ネイピア') then 'yes' else 'no'

yes
 これはもう、これ以上書くまでもないでしょう。サブクエリと同じように使うのみです。
 このように、なかなか機能豊富なXPath 2.0。言語に制御機構を取り込んでしまっただけはあります。これがどれほど普及するかは不明ですが、普及してもしなくても機能が多いのは事実ですし、何よりXMLを処理する際にはXPath 1.0より明らかに楽ですので、とりあえず覚えておいても損はないでしょう。その上に普及すればもうけもの、といったところですが、XPath 2.0は十分伸び目があります。ただ、XQueryに関してはさほど普及しないであろうというのが私の見立てです。
 多くの標準APIでサポートされていないなど、現状では少々敷居の高い技術であることは確かなのですが、今から覚えておくと色々楽しめそうです。
カテゴリ [開発魔法][社会問題][経済・知的財産] [トラックバック 0][コメント 0]

<-前のページ [3] [4] [5] [6] [7] [8] [9] [10] [11] 次のページ->
- Blog by yamicha.com -