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
カテゴリ表示
 カテゴリ 社会問題 に当てはまるもののみを表示します。

 存在する記事 733 件の中から 21-25 件を表示しています。
新しい臓器提供意思表示カードをつくる改正
2010/03/28(Sun)23:41:43
 臓器移植法の改正により、今後は本人の明確な拒否の意思表明がない限り、家族同意で臓器提供が行われる可能性が出てきましたが、それにあわせて臓器提供意思表示カードの様式も見直されることとなりました。現在パブリックコメントが行われており、それも踏まえて様式の改定が行われるようです。
 これまでは臓器提供に本人同意が必須であったのが、今後は拒否の表明がなければ移植の可能性が出てくる点もさることながら、現行のカードはあまりにも分かりづらいものであったため、その意味でも改定は妥当といえるでしょう。所持者が意思を明確に伝えられ、しかもそれが尊重されるよう、カードはあくまで分かりやすいものでなければなりません。
 パブリックコメントのPDFによれば、現行のカードは以下の通りです。


 現行の臓器提供意思表示カード。

 参考までに、私は以下のデザインのカードを携帯しています。かなり初期のカードですので、現行のものとは表面の絵が違いますが、質問はおおむね同様です。


 初期の臓器提供意思表示カード。「厚生省」に時代を感じる。

 文面の主な差異を挙げておくと、私が所持している初期のカードでは、「眼球」の選択肢が2番にしかありませんが、現行のカードでは1番にも「眼球」が加わっています。また、初期のカードには「眼球(角膜)」と書いてあったのが、現行のものでは「眼球」のみとなっています。それ以外はほぼ同じです。
 一方、やはりパブリックコメントのPDFによれば、新しいカード案として以下のようなものが提示されています。


 新しい臓器提供意思表示カード案。

 以前のカードで発生する可能性のあった問題は、新しいカード案ではそれなりに解決されています。旧来のカードでは、それぞれの項目の下に臓器名が並べられていましたが、
(該当する1.2.3.の番号を○で囲んだ上で提供したい臓器を○で囲んで下さい)
  1. 私は、脳死の判定に従い、脳死後、移植の為に○で囲んだ臓器を提供します。
    (心臓・肺などの臓器名...)
  2. 私は、心臓が停止した死後、移植の為に○で囲んだ臓器を提供します。
    (腎臓・眼球などの臓器名...)
  3. 私は、臓器を提供しません。
 提供したい臓器名を○で囲んでいたとしても、番号を○で囲み忘れるとアウトでした。実は私も当初、このミスを犯したままでカードを携帯しており、新聞社のサイトで「記載不備が多い」旨の記事を読んでようやく気づくに至りました。途中からはある程度弾力的に解釈を行うようになり、記載に少々の不備があっても提供意思が認められるようにはなった模様ですが、臓器移植の開始当初は特に意思が厳密に解釈されていたため、このような些細な記載不備で臓器を提供できない状況が発生していました。
 また、旧カードでは「該当する1.2.3の番号を○で囲」むよう指示されていますが、「自分に該当するものを1つ選べ」という意味か、はたまた「自分に該当するものをすべて選べ」という意味なのかがあいまいです。その上で、仮に前者の意味として1のみを選択していると、「脳死の判定に従った脳死後に臓器を提供するのは構わないが、心臓停止した死後に臓器を提供するのには同意していない」とも解釈されうるという全く意味不明な状況が発生しかねませんでした。さらに、1と2の両方を選択していた場合でも、1については各種臓器に○をつけておいて、2では○を省略していた場合、やはり「脳死後に腎臓などを提供するのは構わないが、心臓停止後に腎臓を提供するのには同意していない」とみなされる余地がありました。
 新しい臓器移植法では、そもそも拒否の意思表示がない限りは臓器提供の可能性があるため、記載不備があっても拒否とみなされない限りは問題がなく、このようなミス自体があまり重要なものではなくなっていますが、それでも文面はある程度分かりやすく修正されています。
(1.2.3.いずれかの番号を○で囲んでください)
  1. 私は、脳死後及び心臓が停止した死後のいずれでも移植の為に臓器を提供します。
  2. 私は、心臓が停止した死後に限り、移植の為に臓器を提供します。
  3. 私は、臓器を提供しません。
(太字は引用者による。提供臓器選択欄は1と2で統一され、提供したい臓器にマル印をつける方式から、提供を希望しない臓器にバツ印をつける方式に変更)
 番号は単一選択であると明確に規定され、原理上おかしかった「脳死後に臓器は提供するが、心臓が停止した死後には臓器を提供しない」という誤った意思表明は存在しなくなっています。また、拒否の意思がなければ臓器提供の可能性がある新移植法を踏まえ、臓器も提供したいものを○で囲む方式から、提供したくないものを除外する方式に変わっています。臓器選択欄も1と2で統一され、意味不明な意思表示が発生しないようになっています。

 ただ、以前のカードに存在した問題はある程度解決されているとはいえ、新しいカード案にも疑問がないわけではありません。
 旧臓器移植法に基づいた旧来のカードには、主に次のような役割がありました。
  • 所持者が脳死判定に同意しているかを明確にすること
  • 所持者が臓器提供に同意しているか、いかなる臓器を提供するかを明確にすること
 これは以前の臓器移植法からして当然の要請でした。旧臓器移植法においては、「脳死は個体死か」という問題もある意味で棚上げされており、脳死判定を行うのにも臓器提供にも本人の同意が必要でした。したがって、本人が脳死判定に同意しているか(すなわち「脳死」を「自らの死」と認めるか)、また脳死判定に同意する場合は脳死後に、そうでなければ従来の方法での個体死認定後に、臓器を提供する意思があるかを確認するのが意思表示カードの主な役割となっていました。
 ところが、新臓器移植法では逆に、本人が拒否の意思を示さない限りは臓器提供がなされる可能性が出てきました。この場合、カードは以下のような役割を果たすことになります。
  • 所持者が条件付きで、あるいはいかなる場合でも臓器を提供しない意思を表明すること
  • 所持者が臓器提供自体には同意していても、特定の臓器は提供しない意思を表明すること
  • 所持者が臓器提供の意思があることを家族に対して明確にすること
 ここで重要なのは3番目です。
 これまでの臓器移植法においては、臓器を提供したくない場合はカードを持っても持たなくても同じでした。本人が書面(カード)で同意していなければ臓器提供は行われませんし、本人が同意している場合は遺族に確認がなされ、その同意があれば臓器提供が行われていました。この場合、そもそも本人の提供意思が明確でない限り、臓器提供の対象とはならず、遺族への確認は行われないわけですから、遺族に確認がなされる場合は必ず故人が提供意思を持っていることになり、「所持者が家族に意思を明確にする」という機能を考える必要はありませんでした。
 一方、新臓器移植法ではこれが逆転し、本人の拒否がない限り臓器提供の可能性があります。このケースでは、本人が提供の意思を表明している場合もあれば、していない場合もあります。すなわち、カードを持っても持たなくても提供がなされる可能性があるという点では同じなのですが、こちらは以前の場合とは違い、カードがなければ遺族が故人の意思を測りかねる恐れがあります。そうなると、本人が提供の意思を示していれば提供に同意したであろう遺族が、本人の意思が不明瞭であることを理由に提供を拒む可能性があり、せっかく臓器移植法を改定したにもかかわらず、移植の機会があまり増えない状況にもなりかねません。
 新カード案は、上で示した最初の2つの役割はおおむね満たしているものの、この役割については十分に満たしているか疑問があります。新しい制度自体が「何も表明しなければ提供の可能性あり」なのですから、カードが簡略化されること自体は当然の流れなのですが、それによって意思伝達の側面が希薄になるとすれば、問題があることは否めません。
 例えば、世の中の多くの人は移植についてあまり知識を持たないわけですが、そのような遺族が「故人の眼球の移植に同意するか」と問われたら、果たして抵抗なく同意できるでしょうか。しかも、旧来のカードであれば「眼球」に○をつける必要があり、眼球の提供は故人の意思であると分かりますが、新しいカードではバツ印さえついていなければ同意とみなされます。「バツがついていないから、提供は故人の意思だ」とみなすのは、「マルがついているから、提供は故人の意思だ」とみなすよりも明らかに困難です。せめて「提供の意思を明確にするために、臓器名を○で囲んでも構いません」の注意書きの1つでも入れておけば、それなりに改善される問題ではないでしょうか。
 また、以前に比べて大幅に改善されたとはいえ、例の「番号を○で囲む」スタイルにはあまり賛同できません。私が誤記した経験から申し上げて、あの方法は非常に見落としやすいのです。ここで誤記が発生すると、やはり所持者の意思があいまいになってしまい、意思表示媒体としての役目を十分果たせなくなる懸念があります。この方法を新カードでも用いるのであれば、せめて番号の手前にチェックボックスを置くなど、「ここはただの箇条書き項目ではなく、所持者が記入しなくてはならない部分」と印象付けるような工夫が欲しいところです。
 それから、大変に些細なことではありますが、このブログで以前にQRコードメーカーを作成した際に読んだ仕様書には、「QRコードの周囲4ピクセル分は、コード内の白部分と同じ色の余白でなくてはならない」と書かれていたよう記憶しています。まだ実物のカードが存在しないため、実際の寸法は分かりませんが、パブリックコメントのPDFファイルの画像を見る限り、背景のオレンジ色の部分がQRコードの余白に侵食しているようです。また、こちらは4ピクセル分離れているようにも離れていないようにも見えますが、もし「臓器移植ネットワーク」の「ク」の文字が4ピクセル以内に入っているなら、完全に仕様に反しています。最近の読み取り機器の性能からして、そうそうエラーは出ないはずですが、撮影時の周囲の明るさなどでも彩度は変化するのですから、誤って読み取られる可能性は常に存在しており、利用者に優しいとはいえません。
 また、せっかく良いカードを作っても、所持する人が増えなければ意味がありません。もし今後もカードがあまり普及せず、カード不所持につき遺族同意によって誰かの臓器が提供されたとして、もしその人が周囲に臓器提供反対の意を話していたり、カードによらない方法で提供を拒む意思を遺していたことが後で発覚すれば、新臓器移植法の概念自体が窮地に追い込まれかねません。拒否の意思を担保する意味でも、カードの普及を今以上に図る必要があります。

 JSF 2.0のカスタムコンポーネントでは、属性を使って値やメソッドを受け取ることができました。プロパティやメソッドも使えるとあって、これだけでもそれなりに様々な使い方が可能です。
 ただ、属性だけでは柔軟性の高いコンポーネントの作成は不可能ですし、できたとしても大量の属性を取らなくてはならず、逆に見通しが悪くなります。何らかの要素を記述できるなど、もっと柔軟性のある方法を使用したいところです。
 そんなこんなで探してみたところ、その方法はやはり存在していました。各種資料を読む限り、やり方はいくつか存在するようですが、今回はcomposite:insertChildren及びcomposite:renderFacetを使用しています。
 composite:insertChildrenは単純に、カスタムタグが持つ要素などの子ノードをそのまま貼り付けるもので、使い方は非常に簡単です。カスタムコンポーネントの側ではcomposite:interface内に特に何も書く必要がなく、単にcomposite:implementation内の好きな場所に<composite:insertChildren />を書くだけです。カスタムコンポーネントを使用する際には、その子ノードとして任意の要素なり何なりを持たせておけば、後はinsertChildrenの部分がそれに置き換わります。
 composite:renderFacetは名前つきinsertChildrenのようなものらしく、composite:interfaceで名前の記述が必要な上、renderFacetタグを使用する際にも名前を指定しなくてはならず、呼び出し側でも渡したいノードをf:facetでくくらなくてはなりませんが、より柔軟です。
 これらは併用しても動作するようで、その際にはf:facetの子ノードがそれぞれ対応するcomposite:renderFacetの部分に表示され、f:facetに含まれていない部分がcomposite:insertChildrenに表示されました(GlassFish v3 Previewの場合。他の実装では実験していません)。
 以下、前回のフォームの改良版として、これらの方法をそれぞれ用いたカスタムコンポーネントを作成及び使用しています。
/resources
 /comp
  customFormInput.xhtml
  customLabelInput.xhtml
/WEB-INF
 /classes
  /com
   /yamicha
    /custom
     CustomFormBean.java
 web.xml
customForm.xhtml
customLabel.xhtml
customResult.xhtml
 このうち、customFormInput.xhtml及びcustomForm.xhtmlがcomposite:insertChildrenを用いており、customLabelInput.xhtml及びcustomLabel.xhtmlがcomposite:renderFacetやf:facetを用いています。それ以外の点はほとんど同じです。CustomFormBeanはManagedBean、customResult.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 Custom Component Servlet</display-name>
  <description>JSF 2.0 Custom Component Servlet</description>

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

  <servlet-mapping>
    <servlet-name>jsf20custom</servlet-name>
    <url-pattern>*.jsf</url-pattern>
  </servlet-mapping>
</web-app>
 CustomFormBean.javaも前回のCustomForm.javaと似たり寄ったりですが、今回はnameプロパティがfirstNameとlastNameになり、addressプロパティはaddress1とaddress2になっています。
package com.yamicha.custom;

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.component.html.HtmlInputText;
import javax.faces.bean.*;
import javax.faces.event.*;
import java.util.*;

@ManagedBean @RequestScoped public class CustomFormBean
	implements java.io.Serializable{
	private String fname;
	private String lname;
	private String mail;
	private String webPage;
	private String address1;
	private String address2;

	public CustomFormBean(){
	}

	public String getFirstName(){
		return fname;
	}
	public String getLastName(){
		return lname;
	}
	public String getMail(){
		return mail;
	}
	public String getWebPage(){
		return webPage;
	}
	public String getAddress1(){
		return address1;
	}
	public String getAddress2(){
		return address2;
	}

	public void setFirstName(String n){
		fname = n;
	}
	public void setLastName(String n){
		lname = n;
	}
	public void setMail(String m){
		mail = m;
	}
	public void setWebPage(String w){
		webPage = w;
	}
	public void setAddress1(String a){
		address1 = a;
	}
	public void setAddress2(String a){
		address2 = a;
	}

	public void requiredValidator(FacesContext context ,
		UIComponent component , Object value){
		if(((String)value).isEmpty()){
			HtmlInputText input = (HtmlInputText)component;
			throw new ValidatorException(new FacesMessage(
				input.getLabel() + " は必須項目です。"));
		}
	}
}
 本題はここからです。まずはcomposite:insertChildrenを使用しているカスタムコンポーネント・customFormInput.xhtmlより。
<?xml version="1.0" encoding="Shift_JIS" ?>
<html xmlns="http://www.w3.org/1999/xhtml"
  xmlns:h="http://java.sun.com/jsf/html"
  xmlns:c="http://java.sun.com/jsp/jstl/core"
  xmlns:composite="http://java.sun.com/jsf/composite">

  <composite:interface>
    <composite:attribute name="labelStyleClass" default="" />
    <composite:attribute name="inputStyleClass" default="" />
    <composite:attribute name="indent" default="15" />
    <composite:attribute name="label" />
  </composite:interface>

  <composite:implementation>
    <table border="0" width="90%">
      <tr>
        <td class="#{cc.attrs.labelStyleClass}">
          <h:outputText value="#{cc.attrs.label}" />
        </td>
      </tr>
      <tr>
        <table border="0" width="100%">
          <tr>
            <td width="#{cc.attrs.indent}"></td>
            <td class="#{cc.attrs.inputStyleClass}">
              <composite:insertChildren />
            </td>
          </tr>
        </table>
      </tr>
    </table>
    <br />
  </composite:implementation>
</html>
 前回作成したcustomInput.xhtmlとの違いといえば、せいぜいh:inputTextを使用していた部分が、今回はcomposite:insertChildrenに変わっているだけです。それに伴ってcomposite:interfaceでの属性の指定も少なくなっていますが、これは副次的な変化です。
 これはcustomForm.xhtmlで使用しています。
<?xml version="1.0" encoding="Shift_JIS" ?>
<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"
  xmlns:cc="http://java.sun.com/jsf/composite/comp">

<h:head>
  <title>JSF 2.0 Custom Component</title>
  <style type="text/css">
    td.label { background-color: #CCDDFF; }
  </style>
</h:head>

<h:body>
  <b>送信フォーム</b><br />
  <small>(*)必須項目</small>

  <h:form>
    <cc:customFormInput label="氏名(*)" labelStyleClass="label">
      氏名を入力してください。<br />
      First <h:inputText value="#{customFormBean.firstName}"
        validator="#{customFormBean.requiredValidator}"
        label="First Name" /> / 
      Last <h:inputText value="#{customFormBean.lastName}"
        validator="#{customFormBean.requiredValidator}"
        label="Last Name" />
    </cc:customFormInput>

    <cc:customFormInput label="メールアドレス(*)" labelStyleClass="label">
      メールアドレスを入力してください。<br />
      <h:inputText value="#{customFormBean.mail}" size="40"
        validator="#{customFormBean.requiredValidator}"
        label="メールアドレス" />
    </cc:customFormInput>

    <cc:customFormInput label="Web ページ" labelStyleClass="label">
      Web ページをお持ちなら、アドレスを入力できます。<br />
      <h:inputText value="#{customFormBean.webPage}" size="60" />
    </cc:customFormInput>

    <cc:customFormInput label="在住地域" labelStyleClass="label">
      公開可能な範囲で在住地域を入力できます。<br />
      <br />

      国・都道府県・州・市区町村<br />
      <h:inputText value="#{customFormBean.address1}" size="60" /><br />
      地域・番地<br />
      <h:inputText value="#{customFormBean.address2}" size="60" />
    </cc:customFormInput>

    <h:commandButton action="customResult" value="送信" />
  </h:form>
</h:body>

</html>
 今回はここで入力フォームを記述しています。これで前回のようにバリデータを渡す必要がなくなった他、何でも自由に記述できるようになっているため、上記のように複数個のh:inputTextを用意できたり、h:inputText以外のものを配置できたりと、自由度が増しています。
 これに対して、component:renderFacetを使用するコンポーネントも作成してみます。まずはカスタムコンポーネントのcustomLabelInput.xhtmlより。
<?xml version="1.0" encoding="Shift_JIS" ?>
<html xmlns="http://www.w3.org/1999/xhtml"
  xmlns:h="http://java.sun.com/jsf/html"
  xmlns:c="http://java.sun.com/jsp/jstl/core"
  xmlns:composite="http://java.sun.com/jsf/composite">

  <composite:interface>
    <composite:attribute name="labelStyleClass" default="" />
    <composite:attribute name="inputStyleClass" default="" />
    <composite:attribute name="indent" default="15" />
    <composite:facet name="label" />
    <composite:facet name="form" />
  </composite:interface>

  <composite:implementation>
    <table border="0" width="90%">
      <tr>
        <td class="#{cc.attrs.labelStyleClass}">
          <composite:renderFacet name="label" />
        </td>
      </tr>
      <tr>
        <table border="0" width="100%">
          <tr>
            <td width="#{cc.attrs.indent}"></td>
            <td class="#{cc.attrs.inputStyleClass}">
              <composite:renderFacet name="form" />
            </td>
          </tr>
        </table>
      </tr>
    </table>
    <br />
  </composite:implementation>
</html>
 今度はcomponent:interface内にcomposite:facetを記述しています。ここでは、label及びformという名前のfacetを用いることを指定しています。また、insertChildrenの代わりにrenderFacetを用いています。
 ちなみに、これとは別にcomposite:insertFacetなるタグが存在しているようですが、こちらは使用しても全く機能しませんでした。どうもJSF 2.0人口は恐ろしく少ないらしく、検索してもこれといった資料が出てきませんでしたが、何か別の使い道があるのでしょうか。
 このカスタムコンポーネントは、customLabel.xhtmlで使用しています。
<?xml version="1.0" encoding="Shift_JIS" ?>
<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"
  xmlns:cc="http://java.sun.com/jsf/composite/comp">

<h:head>
  <title>JSF 2.0 Custom Component</title>
  <style type="text/css">
    td.label { background-color: #CCDDFF; }
  </style>
</h:head>

<h:body>
  <b>送信フォーム</b>

  <h:form>
    <cc:customLabelInput labelStyleClass="label">
      <f:facet name="label">
        氏名<small style="color: red">(必須)</small>
      </f:facet>
      <f:facet name="form">
        氏名を入力してください。<br />
        First <h:inputText value="#{customFormBean.firstName}"
          validator="#{customFormBean.requiredValidator}"
          label="First Name" /> / 
        Last <h:inputText value="#{customFormBean.lastName}"
          validator="#{customFormBean.requiredValidator}"
          label="Last Name" />
      </f:facet>
    </cc:customLabelInput>

    <cc:customLabelInput labelStyleClass="label">
      <f:facet name="label">
        メールアドレス<small style="color: red">(必須)</small>
      </f:facet>
      <f:facet name="form">
        メールアドレスを入力してください。<br />
        <h:inputText value="#{customFormBean.mail}" size="40"
          validator="#{customFormBean.requiredValidator}"
          label="メールアドレス" />
      </f:facet>
    </cc:customLabelInput>

    <cc:customLabelInput labelStyleClass="label">
      <f:facet name="label">
        Web ページ
      </f:facet>
      <f:facet name="form">
        Web ページをお持ちなら、アドレスを入力できます。<br />
        <h:inputText value="#{customFormBean.webPage}" size="60" />
      </f:facet>
    </cc:customLabelInput>

    <cc:customLabelInput labelStyleClass="label">
      <f:facet name="label">
        在住地域
      </f:facet>
      <f:facet name="form">
        公開可能な範囲で在住地域を入力できます。<br />
        <br />

        国・都道府県・州・市区町村<br />
        <h:inputText value="#{customFormBean.address1}" size="60" /><br />
        地域・番地<br />
        <h:inputText value="#{customFormBean.address2}" size="60" />
      </f:facet>
    </cc:customLabelInput>

    <h:commandButton action="customResult" value="送信" />
  </h:form>
</h:body>

</html>
 今回は入力フォームに加え、ラベルも自分で書けるようにしています。
 この両者はどちらも、customResult.xhtmlを結果表示ページとしています。
<?xml version="1.0" encoding="Shift_JIS" ?>
<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"
  xmlns:cc="http://java.sun.com/jsf/composite/comp">

<h:head>
  <title>JSF 2.0 Custom Component - Result</title>
</h:head>

<h:body>
  以下のデータが送信されました。

  <h:panelGrid border="1" columns="2">
    <h:outputText value="名前" />
    <h:panelGroup>
      <h:outputText
        value="#{customFormBean.firstName} #{customFormBean.lastName}" />
    </h:panelGroup>

    <h:outputText value="メールアドレス" />
    <h:outputText value="#{customFormBean.mail}" />

    <h:outputText value="Web ページアドレス" />
    <h:outputText value="#{customFormBean.webPage}" />

    <h:outputText value="在住地域" />
    <h:panelGroup>
      <h:outputText value="#{customFormBean.address1}" />
      <h:outputText value="#{customFormBean.address2}" />
    </h:panelGroup>
  </h:panelGrid>
</h:body>

</html>
カテゴリ [開発魔法][社会問題] [トラックバック 0][コメント 0]

民主民主主義人民共和国
2010/03/22(Mon)21:32:53
 マスコミにおいて小沢氏批判を行った生方氏が、副幹事長を解任されました。民主党側は「外部に向かって批判するのは副幹事長の職責から言って問題がある」ことを理由としていますが、これには外部はもとより党内からも批判が出ており、さらには小沢独裁体制をなおさら印象付けかねない処分とあって、党へのダメージは必ずしも少なくないとみられます。
 つくづく、民主党執行部は一体何を考えているのでしょうか。ここで民主党が適切に党内をまとめ、まっとうな政策実現に向けて努力することは、単に自党の支持を拡大するのみならず、日本に政権交代のある政治をもたらすのにも必要不可欠な行為です。それを放棄しようものなら、民主党内で問題が噴出する分にはまだしも、日本に対して多大なる悪影響を及ぼす結果となります。
 民主党は自民党の受け皿として政権を奪取するに至りましたが、それも自民党への失望、民主党への期待があってこそです。ところが、一連の献金騒動でクリーンさに疑問符がつき、少なくとも裏金の面では自民党と同じであるとみなされても文句を言えない状態となりました。その上に自党の体制を批判すれば役職を解任されるとなれば、クリーンさに続いて党内の透明性もなくなり、党内における自由闊達な議論は消えうせるでしょう。まさに恐怖政治の縮図のようなもので、悪印象を持たれることは避けられませんし、国民の側としても悪印象を持たないわけにはいきません。
 執行部側は処分理由を「外部に向かって批判するのは職責からして問題」であるからとしていますが、まず納得のできるものではありません。同列に扱えるものではないとはいえ、以前に田母神氏や「美辞麗句」発言の自衛隊員が処分されるなどしましたが、これは文民統制が侵害されるという現実的かつ重大なリスクに対するもので、いずれも処分は妥当なものです。しかし、生方氏は自衛隊でいうところの「文民統制」に匹敵するほど重大なリスクのある発言を行ったわけではありませんし、逆に執行部が「小沢氏批判は重大な問題行為」と捉えているのであれば、そちらの方が問題です。
 さらに悪いことに、生方氏が主張している通り、国民の多くは小沢氏に強い疑惑と不審の目を向けており、その政治手法や「小沢党首」以後の民主党の政策及び政党の変質も相まって、小沢氏は辞任すべきであると考えています。しかし、それを代弁した生方氏は副幹事長を解任されてしまいました。執行部は小沢氏への批判を封殺したつもりでも、氏への風当たりはなおさら強くなると考えるべきでしょう。そして、氏が辞任するならそれに越したことはありませんが、辞任せずに「隠者」の地位にしがみついている限り、小沢氏への風当たりは民主党への評価に直結し、民主党が継続的にダメージを受けるであろうことは見えています。
 本件における最も大きな被害者は、まじめに活動している民主党議員や閣僚に他なりません。自民党の流れを汲んだ小沢氏や鳩山氏の資金疑惑、そして今回の言論封殺などから、「民主党も自民党と変わらない」という印象を持つ人は多いようですし、言論封殺までやるようでは持たれて当然でもありますが、そのせいで民主党や政権交代の功績が完全に無となってしまっています。
 外国人参政権や子ども手当ては手放しで評価はできないにしても、55年体制から長きにわたって続いた自民党体制から政権を奪取し、政権交代前までは情報もろくに得られなかった中で、半年余りで「ない」はずの密約を白日の下にさらし、経団連の献金あっせんを中止に追い込み、本来は自民党政権からの「宿題」であった高校無料化にも道を開いています。まだ実現は未定とはいえ、自民党政権下では門前払いになっていたであろう夫婦別姓、取り調べ可視化などの議論も出てきていますし、「子ども手当て」というやり方はともかく、あまりにも矛盾が多すぎる配偶者控除を廃止し、これを子どもへ振り向けるという発想自体は、評価しない理由がありません。ところが、いくら閣僚や議員が努力して功績を挙げたとしても、小沢氏の保身と今回の言論封殺の1つで、それらはすべて消し飛んでしまうのです。
 さらには、自民党は児童ポルノの規制強化と対象拡大を急進的に行なおうとしたり、その他にも国民の自由を制限する法制に積極的であるなど、一歩間違えば中国のような状況になってもおかしくない規制強化がなされかねない危うさがありますが、民主党政権ではそのような状況が発生する可能性は自民党より低く、それも民主党の評価点の1つに挙げられます。しかし、党内ですら独裁国家の真似事をやっているようでは、ましてや国民の自由を守る気があるのかという点にさえ疑問が出てきます。事実、生方氏は「民主党は、小沢さんが白と決めれば全部白だという政党になってしまった。言論の自由がない政党が、国民の言論の自由を保障できるのか」と述べ、この懸念を表明しています。実現するには問題も多く、少なくとも拙速を避けるべきである外国人参政権などの制度が、小沢氏の肝いりとなれば非常にあっさり導入される可能性が出てくる点からも、この懸念が決して夢物語でないことが読み取れます。
 本件のようなゴタゴタにおいて、最も得をするのは一体誰でしょうか。本来なら二大政党の他方である自民党と言いたいところですが、「和魂党」や田母神氏の擁立未遂にとどまらず、今度は週刊誌などで話題の「美し過ぎる市議」なる人物を参院選の候補に立てようとしているようです。このような行為を繰り返している限り、民主党がどうなろうと自民党は没落したままでしょう。事実、民主党への風当たりが強まる一方で、自民党への失望が消える気配はありません。
 それでは誰が利を得るかといえば、「みんなの党」などの第三極もさることながら、兄弟ともども疑念を持たれている鳩山邦夫氏や、「今の自民党に必要なのは、民主党の小沢氏以上の独裁者」であると述べた舛添氏ではないでしょうか。特に舛添氏は到底評価できるような人物ではないにもかかわらず、なぜか人気だけは高く、特に強い懸念があります。言うまでもありませんが、これらのような議員が「明治維新」の真似をしたところで、ろくなことにならないのは見えています。
 政権交代のある政治を定着させるためにも、舛添氏のような人物の台頭を防ぐためにも、民主党は言論封殺や独裁ごっこをしている状況ではありません。今回の言論封殺によって小沢氏への風当たりがさらに強まる可能性は十分にありますが、和らぐとはまず考えられません。党内にも小沢氏への不満は鬱積しており、下手をすると内乱が発生する恐れさえあります。生方氏を切るよりも、小沢氏にご退場を願って党を立て直すべきでしょう。

 前回でひとまず複合コンポーネントの基礎が分かりましたので、今回はもう少しまともに使えそうなコンポーネントを作成し、複数回の呼び出しを行ってみました。今回はManagedBeanも使用しています。
/resources
 /comp
  labelInput.xhtml
/WEB-INF
 /classes
  /com
   /yamicha
    /custom
     FormBean.java
 web.xml
custom.xhtml
result.xhtml
 架空の個人情報登録フォームを想定しています。フォームでは氏名、メールアドレス、Webページ、居住地を入力できるようになっています(前2つは必須、後は任意)。これはサンプルですので実際に登録はしませんが、EJBと組み合わせるなりすれば、当然ながらデータの永続化は可能です。テキストボックス周りのデザインを複合コンポーネント化しています。
 web.xmlは前回と全く同じです。web.xmlといい、JPA使用時のpersistence.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 Custom Component Servlet</display-name>
  <description>JSF 2.0 Custom Component Servlet</description>

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

  <servlet-mapping>
    <servlet-name>jsf20custom</servlet-name>
    <url-pattern>*.jsf</url-pattern>
  </servlet-mapping>
</web-app>
 FormBean.javaでは使用する4情報を扱っている他、バリデータも用意しています。
package com.yamicha.custom;

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 @RequestScoped public class FormBean
	implements java.io.Serializable{
	private String name;
	private String mail;
	private String webPage;
	private String address;

	public FormBean(){
	}

	public String getName(){
		return name;
	}
	public String getMail(){
		return mail;
	}
	public String getWebPage(){
		return webPage;
	}
	public String getAddress(){
		return address;
	}

	public void setName(String n){
		name = n;
	}
	public void setMail(String m){
		mail = m;
	}
	public void setWebPage(String w){
		webPage = w;
	}
	public void setAddress(String a){
		address = a;
	}

	public void requiredValidator(FacesContext context ,
		UIComponent component , Object value){
		if(((String)value).isEmpty()){
			HtmlInputText input = (HtmlInputText)component;
			throw new ValidatorException(new FacesMessage(
				input.getLabel() + " は必須項目です。"));
		}
	}
	// 何もチェックしないバリデータメソッド
	public void throughValidator(FacesContext context ,
		UIComponent component , Object value){
	}
}
 何もしないバリデータは苦肉の策です。
 labelInput.xhtmlが複合コンポーネントとなっています。
<?xml version="1.0" encoding="Shift_JIS" ?>
<html xmlns="http://www.w3.org/1999/xhtml"
  xmlns:h="http://java.sun.com/jsf/html"
  xmlns:c="http://java.sun.com/jsp/jstl/core"
  xmlns:composite="http://java.sun.com/jsf/composite">

  <composite:interface>
    <composite:attribute name="label" />
    <composite:attribute name="describe" default="" />
    <composite:attribute name="value" />
    <composite:attribute name="labelStyleClass" default="" />
    <composite:attribute name="inputStyleClass" default="" />
    <composite:attribute name="inputValidator" required="true"
      method-signature=
"void validator(javax.faces.context.FacesContext,javax.faces.component.UIComponent,java.lang.Object)" />
    <composite:attribute name="size" default="" />
    <composite:attribute name="indent" default="15" />
  </composite:interface>

  <composite:implementation>
    <table border="0" width="90%">
      <tr>
        <td class="#{cc.attrs.labelStyleClass}">
          <h:outputText value="#{cc.attrs.label}" />
        </td>
      </tr>
      <tr>
        <table border="0" width="100%">
          <tr>
            <td width="#{cc.attrs.indent}"></td>
            <td class="#{cc.attrs.inputStyleClass}">
              <h:outputText value="#{cc.attrs.describe}" /><br />
              <h:inputText label="#{cc.attrs.label}" size="#{cc.attrs.size}"
                value="#{cc.attrs.value}"
                validator="#{cc.attrs.inputValidator}" />
            </td>
          </tr>
        </table>
      </tr>
    </table>
    <br />
  </composite:implementation>
</html>
 ほとんど前回の応用ですが、普通の属性でメソッドを受け取ろうとするとエラーになってしまいます。メソッドを受けたい場合には、method-signatureを指定しなくてはなりません。今回は"void validator(javax.faces.context.FacesContext,javax.faces.component.UIComponent,java.lang.Object)"となっていますが、意味は見ての通りでしょう。
 ただ、色々探してはみたものの、メソッドを渡したくない場合の記述が見つかりませんでした。今回はこれをバリデータメソッドを渡すために使用しているため、バリデータを使わない場合は省略したいところなのですが、属性の記述を省略したり、"null"などと入力してみたりしても、いずれもエラーとなってしまいます。仕方がないので何もしないバリデータを作成するという苦肉の策を使用していますが、実際には何かもっと上手い手がありそうです。
 このコンポーネントはcustom.xhtmlで使用しています。
<?xml version="1.0" encoding="Shift_JIS" ?>
<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"
  xmlns:cc="http://java.sun.com/jsf/composite/comp">

<h:head>
  <title>JSF 2.0 Custom Component</title>
  <style type="text/css">
    td.label { background-color: #CCDDFF; }
  </style>
</h:head>

<h:body>
  <b>送信フォーム</b><br />
  <small>(*)は必須項目</small>

  <h:form>
    <cc:labelInput label="名前(*)"
      describe="お名前を入力してください。"
      value="#{formBean.name}" labelStyleClass="label"
      inputValidator="#{formBean.requiredValidator}" />

    <cc:labelInput label="メールアドレス(*)"
      describe="メールアドレスを入力してください。"
      value="#{formBean.mail}" labelStyleClass="label" size="40"
      inputValidator="#{formBean.requiredValidator}" />

    <cc:labelInput label="Web ページ"
      describe="Web ページをお持ちなら、アドレスを入力できます。"
      value="#{formBean.webPage}" labelStyleClass="label" size="60"
      inputValidator="#{formBean.throughValidator}" />

    <cc:labelInput label="在住地域"
      describe="公開可能な範囲で在住地域を入力できます。"
      value="#{formBean.address}" labelStyleClass="label" size="60"
      inputValidator="#{formBean.throughValidator}" />

    <h:commandButton action="result" value="送信" />
  </h:form>
</h:body>

</html>
 result.xhtmlで結果を表示しています。これはサンプルですから、ただ送信データを表示するだけですが、後は書き方次第です。
<?xml version="1.0" encoding="Shift_JIS" ?>
<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"
  xmlns:cc="http://java.sun.com/jsf/composite/comp">

<h:head>
  <title>JSF 2.0 Custom Component - Result</title>
</h:head>

<h:body>
  以下のデータが送信されました。

  <h:panelGrid border="1" columns="2">
    <h:outputText value="名前" />
    <h:outputText value="#{formBean.name}" />

    <h:outputText value="メールアドレス" />
    <h:outputText value="#{formBean.mail}" />

    <h:outputText value="Web ページアドレス" />
    <h:outputText value="#{formBean.webPage}" />

    <h:outputText value="在住地域" />
    <h:outputText value="#{formBean.address}" />
  </h:panelGrid>
</h:body>

</html>
 複合コンポーネントの作成が簡単なおかげで、「コンポーネントを作るよりそのまま書いた方が手間も時間も記述量もマシ」という意味の分からない状況に陥らないのが助かります。
カテゴリ [開発魔法][社会問題] [トラックバック 0][コメント 0]

時効の功罪
2010/03/14(Sun)21:13:13
 殺人の公訴時効を廃止する改正案が閣議決定されました。今国会での成立、6月までの施行を目指すようです。今回の改正では、人を死亡させた場合の時効が延長されることとなっており、殺人など死刑にあたる罪の時効は廃止、傷害致死や業務上過失致死、危険運転致死などは時効が倍程度に延長されます。また、施行日以前に発生した事件であっても、施行の時点で時効を迎えていないものに対しては、新しい期間が遡及適用されます。また、「刑の時効」を廃止または延長する改正案も同日に閣議決定されました。
 まずは時効に関して簡単におさらいをしておきましょう。一般的に言われる「時効」とは「公訴時効」のことで、現状では刑事訴訟法第二百五十条によって以下のように定められています。
第二百五十条  時効は、次に掲げる期間を経過することによつて完成する。
一  死刑に当たる罪については二十五年
二  無期の懲役又は禁錮に当たる罪については十五年
三  長期十五年以上の懲役又は禁錮に当たる罪については十年
四  長期十五年未満の懲役又は禁錮に当たる罪については七年
五  長期十年未満の懲役又は禁錮に当たる罪については五年
六  長期五年未満の懲役若しくは禁錮又は罰金に当たる罪については三年
七  拘留又は科料に当たる罪については一年
 なお、公訴時効が上記の通り改正されたのは2005年のことで、それまでは死刑に当たる罪の時効が15年、無期懲役・禁錮が10年、長期10年以上の懲役・禁錮は7年とされていました。それ以下の部分は改正後と同じです。今回の案が成立すれば、わずか5年での時効再延長となります。
 一方「刑の時効」とは、刑の言い渡しが確定した後、一定期間その執行を受けないことで完成するもので、こちらは刑法第三十二条で定められています。
(時効の期間)
第三十二条  時効は、刑の言渡しが確定した後、次の期間その執行を受けないことによって完成する。
一  死刑については三十年
二  無期の懲役又は禁錮については二十年
三  十年以上の有期の懲役又は禁錮については十五年
四  三年以上十年未満の懲役又は禁錮については十年
五  三年未満の懲役又は禁錮については五年
六  罰金については三年
七  拘留、科料及び没収については一年
 科料の踏み倒し程度ならともかく、死刑などの重罰が数十年も執行できず、時効が成立するケースというのはほとんど考えられませんので、公訴時効に比べれば改正の影響は少ないといえるでしょう。ちなみに、30年以上収監されている死刑囚(帝銀事件)の支援者が、死刑の執行が30年なかったのだから時効が完成したはずであると訴えたことがありましたが、案の定認められませんでした(最高裁昭和60年7月19日 判時1158号28頁。刑法34条を理由に時効は停止しているとみなされる)。

 殺人の公訴時効の撤廃については、自民党政権時代からの「宿題」であるとはいえ、今なお懸念が全く解消されておらず、かなり時期尚早な印象が否めません。最近は被害者遺族らがマスコミに顔を出す機会も増えており、以前に比べて時効の問題が注目されているのは事実ですが、基本的には時効の延長・撤廃には慎重であるべきで、少なくとも十分な議論と検証の上で決定されなくてはなりません。
 各社が行っている世論調査でも、殺人の公訴時効の撤廃を求める声が大多数のようですが、国民の間でも時効撤廃のリスクがあまりにも周知不足であると言わざるを得ません。本来なら時効撤廃のリスクについて説明するのもマスコミの役割に含まれるはずですが、一部マスコミに至っては露骨な印象操作まで行う有様で、そのような役割は到底期待できたものではありません。
 例を挙げれば、時効が存在する理由として「時間が経てば被害者感情が和らぐ」「時効までの逃亡で犯人も苦痛を味わう」なるものがあると紹介し、それに対して被害者遺族の声を引用するなどして反論、時効撤廃を正当化する手法を一部新聞などが用いていましたが、法解釈上はそれに似た意見があるとはいえ、昨今でそのような主張をする撤廃慎重派を、少なくとも私は一度も見たことがありません
 実際問題として、「時間が経てば被害者感情が和らぐ」から罪に問わないことが許されるのであれば、天涯孤独の人を殺害した場合には被害者感情が存在しないのですから、犯人を罪に問う理由がなくなります。また、「犯人が逃亡で苦痛を味わう」から罪に問わないことが許されるのであれば、犯人が時効寸前に逮捕された場合には、無罪に準じるほど軽い罰を与えるのでなければ理屈に合いません。すなわち、これらの理屈はそもそも破綻しており、最も大事な理由を完全に無視しておきながら、このようなものをわざわざ撤廃反対理由として持ち出そうとするのは、あまりにも恣意的な印象操作であると結論するよりありません
 時効延長・撤廃においてまず考えなくてはならないのは、「被害者感情が和らぐ」などといういい加減なものではなく、冤罪の可能性に他なりません。すなわち、もし突如として数十年前の事件の犯人にされてしまったら、一体どのようにして無罪を証明すればよいのでしょうか。証拠は散逸し、目撃者も見つからず、無罪の証明が至難の業であるのは疑いようもありません。
 そもそも、捜査に割けるリソースが有限である以上、仮に時効が撤廃されたとしても、いずれは捜査を打ち切らなくてはなりません。時効が無期限だからといって、捜査も無期限に行うことは実質的に不可能ですし、証拠の散逸によって解決も非常に難しくなります。数十年前の事件を1件解決する代わりに最近の事件を10件迷宮入りにするのでは意味がなく、どうしても苦渋の決断が必要となります。
 無論、それでもDNAなどの証拠が残っている限り、何らかの拍子に犯人が発見される可能性はあり、その際に起訴できるという意味では、時効の撤廃は無意味ではありません。交通違反や軽犯罪など些細なことから足がつく可能性もありますので、犯人に与えるプレッシャーもかなりのものでしょう。
 しかし、仮にDNAの照合によって被疑者が見つかったとしても、その場合にはDNAのみが主要な証拠となり、他の証拠は散逸して得られないというケースが多くなるものと予想されます。DNA鑑定の精度はかなり向上していますし、今後も向上する一方ではあるはずですが、仮にDNA鑑定の精度が完璧であったとしても、数十年前の試料が正当なものであると誰に言えるのでしょうか。試料にミスがある可能性もあれば、時として意図的なすり替えが行われている可能性すら否定できません。また、検察側の鑑定結果に疑念があっても、その鑑定で試料がすべて使用され、追試ができない状況に置かれていたら、被告人の側は一体どのようにして無罪を証明するのでしょうか。
 さらに悪い場合、DNAだけでは証拠能力に疑念を抱かれかねないからと、警察や検察が被疑者を恫喝し、ウソの自白や証拠を作り上げてしまう危険すらあります。そうなると、まさに足利事件の再来ともいえる状況が生じるでしょう。本来、裁判において自白は重く考慮してはならないはずですが、DNA型の一致の上に自白もあるとなれば、被告人の不利さは言うまでもありません。
 このように、時効の撤廃・延長には非常に重いリスクがあります。それでも時効の撤廃や延長がどうしても必要であるというなら、十分な議論の上でそれを行うことに反対する気はありませんが、それなら5年前の公訴時効改正の際になされたであろう検討・議論には一体何の意味があったのでしょうか。
 2005年の公訴時効改正では、殺人など死刑に当たる罪の時効が15年から25年に、実に倍近くも延長されています。時効撤廃ほどではないにせよ、これでも冤罪のリスクは高まるわけですから、当時もそれなりの議論はなされたはずです。ところが、今のところ前回の改正からまだ5年しか経っておらず、しかもこの改正は遡及して適用されないため、25年時効が適用されたケースは未だ皆無です。すなわち、現状で時効となっているのは時効が15年の事件のみであり、撤廃どころか殺人の時効を倍近くに延長した場合の知見すら、全く得られていないのです。
 さらには、今回の時効撤廃は遡及適用がなされるものとされています。すなわち、殺人の時効が25年に延長された後、それが一度も効果を発揮せずに時効が撤廃される計算となります。つまり、人命を奪う以外で死刑に当たる罪、あるいは最高刑が死刑以外の罪に関しては、2005年の改正が一応の意味を持ちますが、時効の10年延長の第一のターゲットであるとみられる殺人に関しては、2005年の延長時になされた議論はすべて無駄であった、あるいは当時の議論や決定、リスク評価を無視しているということになります。
 また、この遡及適用に関しても、疑念が多いと指摘せざるを得ません。ひとたび遡及適用を行ってしまうと、際限なく時効の延長を遡及適用する余地を残すことになり、時の政府の思想次第では時効自体が意味を持たなくなりかねません。時効の延長・撤廃に上記のようなリスクがある点を考慮すると、これは危険な状態といえます。また、時効撤廃をまじめに検討できるのも、現代の鑑定などの技術や、それを前提とした捜査・試料の管理があってこそですし、これから撤廃を行うにあたっては同時に副作用を最小限にする方策も取ってもらわなければ困りますが、遡及して適用する場合には最大で15年前の殺人事件の時効も撤廃されます。現在の状況を前提として時効撤廃を行うところを、15年前の事件にまで適用してしまって大丈夫なのでしょうか。
 この通り、時効の撤廃・延長は非常に難しい問題をはらんでおり、少なくとも安易に導入すべきではないことだけは確かです。それでもなお時効の延長・撤廃が必要なのであれば、それに反対する気はありませんが、その際には取り調べの可視化の導入、DNAの取り扱いや証拠能力に関する見直しなど、冤罪の危険を軽減する制度・対策を同時に行ったり、時効延長・撤廃が持つ負の側面が周知されなければなりません。ところが、現状の時効撤廃・延長論は「逃げ得は許さぬ」と勇ましい割に、これらの対策がなされているとは言いがたく、どうしてもその面での懸念が否定できません。これでは「拙速に過ぎる」と結論するよりないでしょう。

※2010/03/20追記
 本記事を書いて1週間としないうちに、早速その懸念を裏付けるような問題が発覚しました。以下、毎日新聞のサイトの記事「DNA:誤登録し逮捕状 別人と取り違え 神奈川県警」(2010/03/20付)から一部を引用します。
 昨年11月に横浜市内で起きた窃盗事件で、神奈川県警が現場の遺留物と警察庁が管理するDNA型データベースのDNA型が一致した男性の逮捕状を取ったものの、データベースに登録されていたのは別人のものだったことが県警への取材で分かった。県警が登録段階で取り違えた可能性が高いという。DNA型データベースは捜査の有力な手がかりになるだけに、警察庁は「今回の原因を調査して、同様のことが起きないよう指導していく」とコメントしている。
 時間が経過するにしたがって証拠品の混乱は発生しやすくなり、DNA以外の証拠も見つけにくくなります。上記の取り違えでは冤罪を回避できたようですが、これが何十年も昔の事件となれば、冤罪を回避できるとは限りません。

 JSFには「カスタムコンポーネント」なるものが存在します。その名の通りカスタムなコンポーネントなのですが、これが実は地獄への片道切符でした。JSF 1.xで書いた覚えがあるのですが、意味の分からないJavaコードを書き、XMLに項目を書き加え、JSPを書くなど、JSFに存在するありとあらゆるものを動員しなくてはならないような有様で、地獄など生ぬるいほどでした。
 ところが、IBMの記事を見る限り、JSF 2.0ではxhtmlファイルの1つも書くだけで「複合コンポーネント」が作れるらしいのです。JSF 1.xの地獄絵図を考えると、本当にそれで作成できるのか半信半疑にならざるを得ませんが、ひとまず試してみました。
 ひとまず本当にそれだけで動くのかテストするため、以下のような非常に簡単な編成で作成してみました。
/resources
 /comp
  message.xhtml
/WEB-INF
 web.xml
showmessage.xhtml
 正真正銘xhtmlとweb.xmlだけで、ManagedBeanさえありません。当然、UIComponentを継承したクラスなど存在する余地もありません。これで本当に動作するのでしょうか。
 上記のファイルのうち、message.xhtmlがコンポーネント、showmessage.xhtmlがそれを呼び出すxhtmlとなっています。やはり上記のIBMの記事によれば、複合コンポーネントはresourcesディレクトリ下に置かなくてはならないようです。その下のcompは私が勝手につけたディレクトリ名で、任意の名前で構いません。また、さらにその下に子ディレクトリを作成するなど、階層を深くしても構いません。
 まずは毎回代わり映えのしない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 Custom Component Servlet</display-name>
  <description>JSF 2.0 Custom Component Servlet</description>

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

  <servlet-mapping>
    <servlet-name>jsf20custom</servlet-name>
    <url-pattern>*.jsf</url-pattern>
  </servlet-mapping>
</web-app>
 次にmessage.xhtmlですが、今回は動作テストということで、単に文字を表示するだけのコンポーネントです。
<html xmlns="http://www.w3.org/1999/xhtml"
  xmlns:h="http://java.sun.com/jsf/html"
  xmlns:composite="http://java.sun.com/jsf/composite">

  <composite:interface>
    <composite:attribute name="text" />
    <composite:attribute name="color" default="#000000" required="false" />
  </composite:interface>

  <composite:implementation>
    <font color="#{cc.attrs.color}">
      <h:outputText value="#{cc.attrs.text}" />
    </font>
  </composite:implementation>
</html>
 JSFにしては意外なことに、ほとんど見ての通りです。まずcomposite:interface内にて、使用する属性を宣言しています。ccはJSPでいうところのoutやrequestのように、JSFの側で用意してくれる変数であるらしく、#{cc.attrs.color}でcolor属性の値を取る、といった使い方をするようです。なお、FaceletsのAPIドキュメントによると、requiredはデフォルトでfalseとのことですので、実際にはrequired="false"を書くかは任意です。
 それでは早速、showmessage.xhtmlでこれを使用してみます。
<?xml version="1.0" encoding="Shift_JIS" ?>
<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"
  xmlns:cc="http://java.sun.com/jsf/composite/comp">

<h:head>
  <title>JSF 2.0 Custom Component</title>
</h:head>

<h:body>
  <cc:message text="メッセージ" color="red" />
</h:body>

</html>
 作成したコンポーネントを使用するには、"http://java.sun.com/jsf/composite/..."ネームスペースURIを使用しなくてはなりません。今回はcompディレクトリ下にコンポーネントを置いたため、URIは"http://java.sun.com/jsf/composite/comp"となっていますが、ディレクトリ名が違う場合はここを書き換えるだけのお手軽仕様だそうです。
 要素名はそのままxhtmlのファイル名となります。上記ではcc:messageとなっていますので、message.xhtmlが呼び出される仕組みです。ファイル名によって区別がなされるため、いまいましいXMLによる関連付けからも解放されています。
 しかもJSFらしからぬことに、後はshowmessage.jsfを呼び出すだけで正しく動作してしまいます。JSF 2.0がすごいのか、単にJSF 1.xがひどすぎるのかは不明ですが、実に簡単です。IBMのサイトに書かれている「パーツごとに分けて組み立てる」手法がようやく現実的に使用できるようになりました。
カテゴリ [開発魔法][社会問題] [トラックバック 0][コメント 0]

谷垣おろし
2010/03/07(Sun)22:47:56
 これだけ混迷の状態にありながら、またも自民党内に新たな問題が浮上してきました。今度の問題は、党内からの不満と谷垣おろしという「人災」です。まず舛添氏が谷垣おろしの可能性に言及したのを皮切りに、大物の与謝野氏も谷垣氏の辞任を求める意見を月刊誌に寄稿するなど、まず党内の体制を整えなければならない中、足並みのそろわない状態となっています。
 まず舛添氏に関しては、「批判のない政党は独裁政党」などとして自己の谷垣批判を正当化していますが、この人は以前に「今の自民党に必要なのは、民主党の小沢氏以上の独裁者」であると主張しており、言い分が完全に破綻していますので、この「谷垣おろし」も自己利益のためのものと考えて間違いなく、私利私欲目的の主張ですから気にする必要はありません。しかし、大物の与謝野氏までそれを言い出しているとなると、党内の結束は相当に崩壊していると考えるのが自然です。
 谷垣氏がここまで人気を落とした原因として、自民党の審議拒否戦術があるのは間違いないでしょう。党内でも実効性に疑問が持たれていながら決行した結果、他の野党の同調は得られず、何の成果もなくむざむざと審議に復帰せざるを得なくなり、しかも国民からはあきれられる始末です。ただでさえ甚大なダメージを受けている自民党を、さらに窮地に追い込んだのは間違いありません。
 その他にも、自党が文民統制違反で処分したはずの田母神氏を候補に立てようとしたり、党名が悪いから嫌われるなどと言い出して「和魂党」に変えようとしたりと、確かに谷垣時代の自民党は意味の分からないことばかりを繰り返しており、党内に怒りが堆積するのも当然です。そのような意味で、ここで総裁を取り替えようとする党内の動きはある意味当然でさえあります。
 しかし、問題は自民党内の反谷垣勢力が、一体どこまで自民党の窮状を正確に認識しているかという点です。審議拒否の失敗に加え、「和魂党」などの冗談とも悪ふざけともつかないやり口に業を煮やしているなら分かりますが、安易に「せっかく民主党が敵失状態にあるのに、そこにつけこめないのは谷垣氏の責任」などと考えているのであれば、これは筋違いであると言わなければなりません。事実、与謝野氏は「(鳩山内閣で)普段なら内閣が倒れるような事件が起きているにもかかわらず、自民党の評価が高まっていないことには、深い反省、思いを抱かないといけない」と発言しており、現状が正しく認識できているのかどうか極めて疑問と言わざるを得ません。
 確かに、民主党の不透明な政治資金の問題を追及するのは大事なことですし、国民の多くも事実が明らかになることを望んでいるでしょう。しかし、民主党の汚点を徹底的に追及したからといって、自民党の株が上がるわけではありません。谷垣氏の放った「平成の脱税王」などの文句は耳ざわりこそ良いですが、これで民主党にダメージを及ぼすことはあっても、自民党の状態は回復しません。
 まして、自民党が民主党の不透明さを攻撃するのは、同時に自分の泣き所をも攻撃するようなものです。小沢氏や鳩山氏は自民党の流れを受け継いだ政治家で、自党も散々なまでに問題を起こしてきたのですから、これらへの攻撃は自分への攻撃にも等しい行為ですし、鳩山氏の金銭感覚を批判するのも結構ですが、それを言うなら麻生内閣も同様の理由で国民に見放されています。したがって、これでは国民に「民主党はダメだ」という印象を与えるどころか、「政治家はダメだ」「世襲は感覚がおかしい」という印象を与えることになり、言うまでもなく自民党の支持が回復するわけもありません。すなわち、敵失につけこんだところで共倒れがオチなのです。
 したがって、自民党が支持を回復したいのであれば、政策などにおいて自分が民主党より優れていることをアピールしなくてはなりません。その意味で、谷垣氏は「和魂党」など意味の分からないことを言い出したり、審議拒否で野党ぶりの堪能さを知らしめるなど、確かに及第点とは言いがたい状態であるため、それができる総裁に取り替えるのであれば意味があります。しかし、与謝野氏は「内閣が倒れるような事件が起きているのに、自民党の評価が高まっていない」などと発言しており、これでは総裁が変わったところで全く同じです。
 また、最近は新党結成の話も出てきているようですが、これもまた状況が読めていないと言わざるを得ません。今の自民党から新党ができたところで、それは自民党のクローンがもう1つ作られるだけに他なりません。ただでさえ存在意義の薄い政党が乱立している中、また同様のものを作成する気なのでしょうか。
 「和魂党」などと言い出したり、田母神氏を立てようとしたり、審議拒否などの戦法を取る総裁の首を取り替えるのも、自民党再生の1つの手段ではあるでしょう。しかし、自民党が「敵失につけこめないから自分の支持が回復しない」と考えている限り、総裁をいくら変えたところで、再生の道は遠いと言わなくてはなりません。

 JSF 2.0ではf:ajaxタグでAjaxが使用できますが、これとは別にJavaScriptからAjaxを呼び出す方法もあるようです。せっかくJSF 2.0を使用するのであれば、できる限りJavaScriptを扱うような泥臭いマネはしたくないものですが、状況によっては必要な場面も出てくるでしょう。JavaScriptは不得手な上、JSFのJavaScriptなど右も左も分からないのですが、ひとまず使用してみる必要がありそうです。
 単純なフォームでは実現できないプログラムということで、最近地図などでよく見かける、「ドラッグで画像が変化する」タイプのJSFを作成してみました。
/WEB-INF
 /classes
  /com
   /yamicha
    /dragajax
     Matrix4.java
     @WebServlet AjaxImage.java
     @ManagedBean DragBean.java
 web.xml
drag.xhtml
 Matrix4.javaは計算用、AjaxImage.javaは画像を生成するServletです。
 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 Drag Ajax Servlet</display-name>
  <description>JSF 2.0 Drag Ajax Servlet</description>

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

  <servlet-mapping>
    <servlet-name>jsf20dragajax</servlet-name>
    <url-pattern>*.jsf</url-pattern>
  </servlet-mapping>
</web-app>
 次は画像生成用のServletですが、色々難しいことをやっているように見えて、実は単に「引数に応じた画像を返している」だけです。したがって、実際には単にドラッグした距離を表示して返すだけでも構わないのですが、それではあまりにも味気ないため、このような面倒な内容となっています。応用次第で地図にでも何にでもできるため、色々な用途に使ってみるのも面白いのではないでしょうか。
 言うまでもありませんが、Matrix4.javaはただのマトリックスであるため、Servlet中で使わないなら用意する必要はありません。
// Matrix4.java
package com.yamicha.dragajax;

// 今回必要な処理のみ実装した、簡易マトリックスクラス
public class Matrix4{
	private double matrix[][];
	private final static int SIZE = 4;

	public final static int X = 0;
	public final static int Y = 1;
	public final static int Z = 2;
	public final static int H = 3;

	public Matrix4(){
		matrix = new double[SIZE][SIZE];
		for(int r = 0; r < SIZE; r++){
			for(int c = 0; c < SIZE; c++){
				matrix[r][c] = 0;
			}
		}
	}
	public Matrix4(double x , double y , double z){
		this();
		set(0 , X , x);
		set(0 , Y , y);
		set(0 , Z , z);
		set(0 , H , 1);
	}
	public double get(int row , int col){
		return matrix[row][col];
	}
	public void set(int row , int col , double value){
		matrix[row][col] = value;
	}

	public Matrix4 multiply(Matrix4 m){
		double n[][] = new double[SIZE][SIZE];

		for(int row = 0; row < SIZE; row++){
			for(int col = 0; col < SIZE; col++){
				double value = 0;
				for(int i = 0; i < SIZE; i++)
					value += get(row , i) *
						m.get(i , col);
				n[row][col] = value;
			}
		}

		matrix = n;
		return this;
	}
	public static Matrix4 rotate(int axis , double rad){
		int c = (axis + 1) % 3;
		int s = (axis + 2) % 3;

		double cos = Math.cos(rad);
		double sin = Math.sin(rad);

		Matrix4 m = new Matrix4();
		m.set(axis , axis , 1);
		m.set(c , c , cos);
		m.set(c , s , sin);
		m.set(s , c , -sin);
		m.set(s , s , cos);
		m.set(H , H , 1);

		return m;
	}
	public static Matrix4 move(double x , double y , double z){
		Matrix4 m = base();

		m.set(H , X , x);
		m.set(H , Y , y);
		m.set(H , Z , z);

		return m;
	}
	public static Matrix4 scale(double x , double y , double z){
		Matrix4 m = new Matrix4();

		m.set(X , X , x);
		m.set(Y , Y , y);
		m.set(Z , Z , z);
		m.set(H , H , 1);

		return m;
	}
	public static Matrix4 base(){
		return scale(1 , 1 , 1);
	}
}

// AjaxImage.java
package com.yamicha.dragajax;

import javax.servlet.annotation.*;
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;
import javax.imageio.*;
import javax.imageio.stream.ImageOutputStream;
import java.awt.*;
import java.awt.image.*;

@WebServlet(name="ajaximage" , urlPatterns={"/image"})
  public class AjaxImage extends HttpServlet{
  public void doGet(HttpServletRequest request ,
    HttpServletResponse response) throws IOException{
    response.setContentType("image/gif");
    OutputStream os = response.getOutputStream();

    try{
      String px = request.getParameter("x");
      String py = request.getParameter("y");
      int x = (px != null && !px.isEmpty()) ? -Integer.parseInt(px) : 0;
      int y = (py != null && !py.isEmpty()) ? -Integer.parseInt(py) : 0;

      // 画像のサイズ
      int width = 200;
      int height = 200;

      // 現在のドラッグ位置から回転度数を生成
      // 画像の幅だけドラッグすると45度
      double dy = ((double)x / width * Math.PI / 4) % (Math.PI * 2);
      double dx = ((double)y / height * Math.PI / 4) % (Math.PI * 2);

      if(dy < 0)
        dy += Math.PI * 2;
      if(dx < 0)
        dx += Math.PI * 2;

      // イメージ作成
      BufferedImage bufimg = new BufferedImage(width , height ,
        BufferedImage.TYPE_INT_ARGB);
      Graphics2D g = bufimg.createGraphics();

      // Graphics2D への描画開始
      g.setColor(Color.black);
      g.fillRect(0 , 0 , width , height);

      Color colors[] = {Color.red , Color.green , Color.blue};

      // 三角形の頂点
      Matrix4 matrixes[] = new Matrix4[3];
      matrixes[0] = new Matrix4(0 , 30 , 0);
      matrixes[1] = new Matrix4(-40 , -40 , 0);
      matrixes[2] = new Matrix4(40 , -40 , 0);

      // 回転
      // ドラッグ分だけ X 及び Y 軸回転し、
      // 最後に Z 方向に100移動
      // (遠近法適用時には物体がある程度離れている必要があるため)
      Matrix4 r = Matrix4.rotate(Matrix4.X , dx).
        multiply(Matrix4.rotate(Matrix4.Y , dy)).
        multiply(Matrix4.move(0 , 0 , 100));

      int points[][] = new int[3][2];

      // 回転を適用し、2D 上の描画位置を算出
      for(int i = 0; i < matrixes.length; i++){
        matrixes[i].multiply(r);

        boolean perspective = "true".equals(request.getParameter("p"));

        if(!perspective){
          // 遠近法を使用しない場合
          points[i][0] = (int)(matrixes[i].get(0 , Matrix4.X) + 0.5);
          points[i][1] = (int)(matrixes[i].get(0 , Matrix4.Y) + 0.5);
        }else{
          // 簡易遠近法
          points[i][0] = (int)(matrixes[i].get(0 , Matrix4.X) *
            ((double)width / 2 / matrixes[i].get(0 , Matrix4.Z)) + 0.5);
          points[i][1] = (int)(matrixes[i].get(0 , Matrix4.Y) * 
            ((double)height / 2 / matrixes[i].get(0 , Matrix4.Z)) + 0.5);
        }

        // 描画を中央にし、Y 座標は反転
        points[i][0] += width / 2;
        points[i][1] = height - (points[i][1] + height / 2);
      }

      // ラインを描画
      for(int i = 0; i < matrixes.length; i++){
        int at = i;
        int next = (i + 1) % 3;

        g.setColor(colors[i]);
        g.drawLine(points[at][0] , points[at][1] ,
          points[next][0] , points[next][1]);
      }

      // 回転度数表示
      g.setColor(Color.white);
      g.drawString("X軸: " + (int)(dx * 180 / Math.PI) +
        " 度" , 10 , height - 30);
      g.drawString("Y軸: " + (int)(dy * 180 / Math.PI) +
        " 度" , 10 , height - 10);

      // 出力
      ImageWriter writer =
        ImageIO.getImageWritersByFormatName("gif").next();

      ImageOutputStream ios = ImageIO.createImageOutputStream(os);
      writer.setOutput(ios);

      writer.write(bufimg);

      ios.close();
      writer.dispose();
    }catch(NumberFormatException e){
    }

    os.close();
  }
}
 地図を作成するのであれば、x及びy引数から必要な地図を生成すると良いでしょう。それ以外にも色々なプログラムが書けそうです。
 ManagedBeanはこれよりかなり単純です。
package com.yamicha.dragajax;

import javax.ejb.*;
import javax.annotation.*;
import javax.faces.bean.*;
import javax.faces.event.*;
import java.util.*;

@ManagedBean @ViewScoped public class DragBean
	implements java.io.Serializable{
	// 累計ドラッグ距離
	private int pos_x;
	private int pos_y;

	// 遠近法の ON/OFF
	private boolean perspective;

	public DragBean(){
		resetPos();
		perspective = true;
	}

	// x 及び y プロパティは drag.xhtml 上で
	// 「差分ドラッグ距離」として使用しているので
	// 取得値は0固定
	public int getX(){
		return 0;
	}
	public int getY(){
		return 0;
	}

	public boolean getPerspective(){
		return perspective;
	}

	// 差分ドラッグ距離を累計分に加算
	public void setX(int x){
		pos_x += x;
	}
	public void setY(int y){
		pos_y += y;
	}

	public void setPerspective(boolean p){
		perspective = p;
	}

	// 累計ドラッグ距離を取得
	public int getPosX(){
		return pos_x;
	}
	public int getPosY(){
		return pos_y;
	}

	// 画像 URL 生成
	// image?x=10&y=10&p=true など
	public String getImageSource(){
		return "image?x=" + getPosX() + "&y=" + getPosY() +
			"&p=" + (getPerspective() ? "true" : "false");
	}

	public void resetPos(){
		pos_x = 0;
		pos_y = 0;
	}
}
 後はXHTMLを残すだけなのですが、これが曲者です。何しろScriptを書くのはここなのですが、何をどうすべきか全く分からないのです。言うまでもなくドキュメントは用意されており、今回使用するのはjsf.ajaxであることまでは大体予想できますが、これを読んで理解できる人は新人類になるべきでしょう。全体的に説明不足で、引数の要求がさっぱり分かりません。
 色々と四苦八苦しつつ、とりあえず以下の点に着目してみました。
<commandButton id="button1" value="submit"
    onclick="jsf.ajax.request(this,event,
      {execute:'button1',render:'status',onevent: handleEvent,
       onerror: handleError});return false;"/>
</commandButton/>
 jsf.ajax.requestの引数は「jsf.ajax.request(source, event, options)」であると説明されています。この場合、thisがsource引数に、eventがevent引数に当たるようです。ちなみに、onclickやondragなどの記述の中でeventと書くと、自分自身のイベントを受け取れます。thisはそのまま自分自身で、jsf.ajax.requestからすれば「イベントのソース」ということになるはずですが、こちらはFirefoxならevent.target、IEならevent.srcElementで取得できます。したがって、引数にeventを取る汎用の関数を書いておいて、ソースはevent.targetやevent.srcElementで取ってjsf.ajax.requestに渡してやれば、割と手軽にプログラムが書けそうです。
 3つ目の引数はオプションですが、これはドキュメントに次のように書かれています。

namevalue
executespace seperated list of client identifiers
renderspace seperated list of client identifiers
oneventfunction to callback for event
onerrorfunction to callback for error
paramsobject containing parameters to include in the request

 executeとrenderはf:ajaxのものと同様として、paramsはリクエストパラメータ、oneventとonerrorはonreadystatechangeの類型と考えるのが妥当でしょう。実際に書いてみたところ、oneventで設定した関数には1つの引数が渡されており、要求が成功するまでに合計3回呼び出されていました。したがって、そのまま処理を書くと複数回実行されてしまいますが、例えば成功の際であれば引数のnameプロパティに"success"が格納されて返ってくるため、それを使って処理を分けられます。
 これ以外の部分は、ほとんど通常のJSFとJavaScriptに準じます。JavaScriptは不得手ですので、コードは何とも見通しが悪いですが、動いてはくれました。
<!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">

<!-- JavaScript ライブラリを読み込ませるための記述 -->
<h:outputScript name="jsf.js" target="head" library="javax.faces" />

<h:head>
  <title>JSF 2.0 Drag Ajax</title>
  <script>
    var start_x = 0;
    var start_y = 0;

    // jsf.ajax.request の onevent コールバック用関数
    // jsf.ajax.request による Ajax リクエストが成功したら
    // 画像の src を dragform:pos:imgsrc のものに変更
    function change(r){
      if(r.name == "success"){
        img = new Image();
        img.src = document.getElementById("dragform:pos:imgsrc").value;
        document.getElementById("imageobj").src = img.src;
      }
    }

    // ドラッグ開始時のマウス位置を設定
    function setFirstPosition(){
      start_x = event.x;
      start_y = event.y;
    }
    // ドラッグ終了時の処理
    function writeDifference(e){
      dif_x = event.x - start_x;
      dif_y = event.y - start_y;

      setFirstPosition();

      document.getElementById("dragform:dif:x").value = dif_x;
      document.getElementById("dragform:dif:y").value = dif_y;

      sendPos(e);
    }
    // 「どれほどの距離をドラッグしたのか」を送信し
    // 「新たな画像の URL」を受信
    // 受信に成功した時点で画像を切り替える
    function sendPos(e){
      jsf.ajax.request(e.target != null ? e.target : e.srcElement , e ,
        {execute:'dragform:dif' , render:'dragform:pos' , onevent:change});

      document.getElementById("dragform:dif:x").value = 0;
      document.getElementById("dragform:dif:y").value = 0;
    }
  </script>
</h:head>

<h:body>
<div align="center">
  <b>JSF 2.0 Drag Ajax</b>
  <br />
  <br />

  <h:form id="dragform">
    <h:panelGroup id="dragimage">
      <img src="#{dragBean.imageSource}" id="imageobj"
        ondragstart="setFirstPosition()"
        ondragend="writeDifference(event)" style="cursor:move" />
    </h:panelGroup>
    <br />

    <h:form id="dif">
      <h:inputHidden id="x" value="#{dragBean.x}" />
      <h:inputHidden id="y" value="#{dragBean.y}" />

      <h:selectBooleanCheckbox value="#{dragBean.perspective}"
        onclick="sendPos(event)" />Perspective
    </h:form>

    <h:form id="pos">
      <h:inputHidden id="imgsrc" value="#{dragBean.imageSource}" />
    </h:form>
  </h:form>

  <h:commandButton action="#{dragBean.resetPos}" value="Reset">
    <f:ajax render="dragform:pos" onevent="change" />
  </h:commandButton>

</div>
</h:body>

</html>
 ドラッグ処理のやり方としては、ondragで次々と処理を行う方法と、ondragendでドラッグ終了時にまとめて処理を行う方法がありますが、ここでは後者を用いています。ondragの場合、ドラッグでマウスが動くたびにイベントが発生し、サーバーに山のようなリクエストが送られるため、Ajaxとしては非常に都合が悪いです。世によくある地図Ajaxなどでも、ondrag中は地図を画面上で動かすなどクライアントサイドの処理にとどめておいて、ondragendなどのタイミングでリクエストを送る場合が多いようです。
 Perspectiveチェックは簡易遠近法の有無、Resetは視点のリセットとなっており、チェックの場合はonclickによって押した時点でsendPosが呼ばれ、画像が更新されます。Resetはf:ajaxを使用しており、JavaScriptを直接呼び出さずに処理しています。


 最初の状態。


 画像を横にドラッグした状態。


 各方向へのドラッグが累積した状態。

 これだけでもかなり様々なことができそうですので、後は応用次第でしょう。
カテゴリ [開発魔法][社会問題] [トラックバック 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]

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