    001/*
    002 * Copyright (c) 2009 The openGion Project.
    003 *
    004 * Licensed under the Apache License, Version 2.0 (the "License");
    005 * you may not use this file except in compliance with the License.
    006 * You may obtain a copy of the License at
    007 *
    008 *     http://www.apache.org/licenses/LICENSE-2.0
    009 *
    010 * Unless required by applicable law or agreed to in writing, software
    011 * distributed under the License is distributed on an "AS IS" BASIS,
    012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
    013 * either express or implied. See the License for the specific language
    014 * governing permissions and limitations under the License.
    015 */
    016package org.opengion.plugin.column;
    017
    018import org.opengion.hayabusa.common.HybsSystem;
    019import org.opengion.hayabusa.common.HybsSystemException;
    020import org.opengion.hayabusa.db.AbstractEditor;
    021import org.opengion.hayabusa.db.CellEditor;
    022import org.opengion.hayabusa.db.DBColumn;
    023import org.opengion.hayabusa.db.Selection;
    024import org.opengion.hayabusa.db.SelectionFactory;
    025import org.opengion.fukurou.util.StringFormat;
    026import org.opengion.fukurou.util.XHTMLTag;
    027import org.opengion.fukurou.util.TagBuffer;
    028
    029/**
    030 * カラムの編集パラメーターのＳＱＬ文の実行結果より、datalistを作成して
    031 * 入力候補となるデータリストを定義する編集用エディタークラスです。
    032 * datalist は、HTML5 から採用されたタグです。
    033 *
    034 * 編集パラメータには、datalistを作成するための、SQL文を記述します。
    035 * このSQL文は、select KEY,LABEL from xx ･･･ という構文で、KEY部分とLABEL部分が
    036 * 選択されます。
    037 * datalist 自身が、HTML5からの新機能なので、現時点では、これ以上の機能はありません。
    038 * 将来的に、DBMENU などと同様に、第三カラム以降を利用可能になると思いますので、
    039 * 今は使わないでください。（将来の機能追加時に互換性問題を引き起こすかもしれませんので）
    040 *
    041 * 入力フィールドとdatalistタグとの関係付は、カラムIDに、"カラムID.sel" で結びつけます。
    042 *
    043 * &lt;input name="カラムID" list="カラムID.sel" /&gt;
    044 * &lt;div style="display:none;"&gt;
    045 *   &lt;datalist id="カラムID.sel"&gt;
    046 *     &lt;option value="KEY1"&gt;LABEL1&lt;/option&gt;
    047 *     &lt;option value="KEY2"&gt;LABEL2&lt;/option&gt;
    048 *     &lt;option value="KEY3"&gt;LABEL3&lt;/option&gt;
    049 *   &lt;/datalist&gt;
    050 * &lt;/div&gt;
    051 *
    052 * divタグは、HTML5 非対応ブラウザを使用した場合、datalist の option がそのまま
    053 * テキストとして見えてしまうのを避けるためです。
    054 *
    055 * 一覧表出力時の getValue( int ,String ) 処理では、Selection オブジェクトの
    056 * キャッシュ機能を利用して、同一Selection オブジェクトの間は、datalist は、
    057 * １度しか、出力しない様に制御しています。これにより、共有のdatalist を使用する為、
    058 * HTMLの出力データ量を抑えることが可能になります。
    059 * (キャッシュを利用しないと１００行出力すると１００個のdatalistを出力する事になります。)
    060 * (同様の機能を持つ INDBMENU では、行ごとにプルダウンデータを作成しています。)
    061 * ただし、行単位にSQLの条件を変える機能(AAA:BBB:CCC:DDD引数)が指定された場合は、
    062 * 行ごとに出力します。
    063 *
    064 * 各カラムの値(value値)に、AAA:BBB:CCC:DDD という値を設定できます。これは、
    065 * $1,$2,$3,$4 に割り当てなおして、QUERYを実行します。また、$1 は、本来の値として、
    066 * メニューの初期値設定等に使用します。上記の例では、AAA が値で、それ以降は、
    067 * 引数になります。
    068 * 又、$Cには自分自身のカラム名を割り当てます。
    069 * この機能を使用すれば、動的メニューを行ごとに条件を変えて作成することが
    070 * 可能になります。
    071 * 例：select KEY,LABEL from xx where KUBUN='$2' and CDK='$3'
    072 * さらに、元の文字列"AAA:BBB:CCC:DDD"は、$0 に割り当てられます。割り当てがない
    073 * 変数は、""(ゼロ文字列)として、扱われます。
    074 *
    075 * カラムの表示に必要な属性は, DBColumn オブジェクト より取り出します。
    076 * このクラスは、DBColumn オブジェクト毎に１つ作成されます。
    077 *
    078 * @og.rev 5.7.4.3 (2014/03/28) 新規作成
    079 * @og.group データ編集(HTML5)
    080 *
    081 * @version  4.0
    082 * @author       Kazuhiko Hasegawa
    083 * @since    JDK5.0,
    084 */
    085public class Editor_DATALIST extends AbstractEditor {
    086        //* このプログラムのVERSION文字列を設定します。   {@value} */
    087        private static final String VERSION = "5.7.6.2 (2014/05/16)" ;
    088
    089        // 5.7.5.0 (2014/04/04) datalist 使用時は、display:none にして、HTML5未対応のブラウザに備える。
    090        private static final String DIV1 = "<div style=\"display:none;\">" ;
    091        private static final String DIV2 = "</div>" ;
    092
    093        private final String query ;
    094        private final String dbid ;
    095        private final String lang ;
    096
    097        private Selection bkSel= null;  // 5.7.5.0 (2014/04/04) Selection オブジェクトのキャッシュ機能
    098
    099        /**
    100         * デフォルトコンストラクター。
    101         * このコンストラクターで、基本オブジェクトを作成します。
    102         *
    103         */
    104        public Editor_DATALIST() {
    105        //      super();
    106                query   = null;
    107                dbid    = null;
    108                lang    = null;
    109        }
    110
    111        /**
    112         * コンストラクター。
    113         *
    114         * @param       clm     DBColumnオブジェクト
    115         */
    116        private Editor_DATALIST( final DBColumn clm ) {
    117                super( clm );
    118                tagBuffer.add( XHTMLTag.inputAttri( attributes ) );
    119
    120                query           = clm.getEditorParam();
    121                dbid            = clm.getDbid();
    122                lang            = clm.getLang();                        // 4.0.0 (2006/11/15)
    123
    124                // 3.5.5.9 (2004/06/07)
    125                if( query == null || query.length() == 0 ) {
    126                        String errMsg = "DATALIST Editor では、編集パラメータは必須です。"
    127                                        + " name=[" + name + "]" + HybsSystem.CR ;
    128                        throw new HybsSystemException( errMsg );
    129                }
    130        }
    131
    132        /**
    133         * 各オブジェクトから自分のインスタンスを返します。
    134         * 自分自身をキャッシュするのか、新たに作成するのかは、各サブクラスの実装に
    135         * まかされます。
    136         *
    137         * @param       clm     DBColumnオブジェクト
    138         *
    139         * @return      CellEditorオブジェクト
    140         */
    141        public CellEditor newInstance( final DBColumn clm ) {
    142                return new Editor_DATALIST( clm );
    143        }
    144
    145        /**
    146         * データの編集用文字列を返します。
    147         *
    148         * ここでは、AAA:BBB:CCC:DDD という値を、$1,$2,$3,$4 に割り当てなおして、
    149         * QUERYを実行します。また、$1 は、本来の値として、メニューの初期値設定等に
    150         * 使用します。上記の例では、AAA が値で、それ以降は、引数になります。
    151         * さらに、元の文字列"AAA:BBB:CCC:DDD"は、$0 に割り当てられます。割り当てがない
    152         * 変数は、""(ゼロ文字列)として、扱われます。
    153         * 又、$Cには自分自身のカラム名を割り当てます。
    154         *
    155         * @og.rev 5.7.5.0 (2014/04/04) datalist 使用時は、display:none にして、HTML5未対応のブラウザに備える。
    156         * @og.rev 5.7.6.2 (2014/05/16) list属性とid属性の結びつきを、name+".sel" に変更
    157         *
    158         * @param       value 入力値
    159         *
    160         * @return      データの編集用文字列
    161         */
    162        @Override
    163        public String getValue( final String value ) {
    164                // input タグの作成
    165                TagBuffer intag = new TagBuffer( "input" );
    166                intag.add( "name"    , name );
    167                if( attributes.get( "id" ) == null || attributes.get( "id" ).length() == 0 ) {
    168                        intag.add( "id"      , name );
    169                }
    170//              intag.add( "list"    , "dl_" + name );          // datalistタグとの関係付けるためのキーワード
    171                intag.add( "list"    , name + ".sel" );         // datalistタグとの関係付けるためのキーワード
    172                intag.add( "value"   , value );
    173                intag.add( "size"    , size1 );
    174                intag.add( tagBuffer.makeTag() );
    175                intag.add( optAttr );
    176
    177                // datalist タグの作成
    178                TagBuffer dltag = new TagBuffer( "datalist" );
    179//              dltag.add( "id"    , "dl_" + name );                    // inputタグとの関係付けるためのキーワード
    180                dltag.add( "id"    , name + ".sel" );                   // inputタグとの関係付けるためのキーワード
    181
    182                dltag = getOption( dltag,value,false );                 // キャッシュは使用しない。
    183
    184                // display:none は、datalist の optionのBODY部が、HTML5 以外では表示されてしまうのを防ぐため。
    185                return intag.makeTag()  + HybsSystem.CR +
    186                                DIV1 + dltag.makeTag() + DIV2 + HybsSystem.CR;
    187        }
    188
    189        /**
    190         * name属性を変えた、データ表示/編集用のHTML文字列を作成します。
    191         * テーブル上の name に 行番号を付加して、名前_行番号 で登録するキーを作成し,
    192         * リクエスト情報を１つ毎のフィールドで処理できます。
    193         *
    194         * ここでは、AAA:BBB:CCC:DDD という値を、$1,$2,$3,$4 に割り当てなおして、
    195         * QUERYを実行します。また、$1 は、本来の値として、メニューの初期値設定等に
    196         * 使用します。上記の例では、AAA が値で、それ以降は、引数になります。
    197         * さらに、元の文字列"AAA:BBB:CCC:DDD"は、$0 に割り当てられます。割り当てがない
    198         * 変数は、""(ゼロ文字列)として、扱われます。
    199         * 又、$Cには自分自身のカラム名を割り当てます。
    200         *
    201         * @og.rev 5.7.5.0 (2014/04/04) datalist 使用時は、display:none にして、HTML5未対応のブラウザに備える。
    202         * @og.rev 5.7.5.0 (2014/04/04) Selection オブジェクトのキャッシュ機能
    203         * @og.rev 5.7.6.2 (2014/05/16) list属性とid属性の結びつきを、name+".sel" に変更
    204         *
    205         * @param       row   行番号
    206         * @param       value 入力値
    207         *
    208         * @return      データ表示/編集用の文字列
    209         */
    210        @Override
    211        public String getValue( final int row,final String value ) {
    212                String name2 = name + HybsSystem.JOINT_STRING + row ;
    213
    214                // 5.7.5.0 (2014/04/04) Selection オブジェクトのキャッシュ機能 (true:使用可能)
    215                boolean useSelCache = value != null && value.indexOf( ':' ) < 0 ;
    216
    217                String listId = useSelCache ? name : name2;             // キャッシュを使用する場合は、共通の name を使う。
    218
    219                // input タグの作成
    220                TagBuffer intag = new TagBuffer( "input" );
    221                intag.add( "name"    , name2 );
    222                if( attributes.get( "id" ) == null || attributes.get( "id" ).length() == 0 ) {
    223                        intag.add( "id"      , name2 );
    224                }
    225//              intag.add( "list"    , "dl_" + listId );                // datalistタグとの関係付けるためのキーワード
    226                intag.add( "list"    , listId + ".sel" );               // datalistタグとの関係付けるためのキーワード
    227                intag.add( "value"   , value );
    228                intag.add( "size"    , size2 );
    229                intag.add( tagBuffer.makeTag() );
    230                intag.add( optAttr );
    231
    232                // datalist タグの作成
    233                TagBuffer dltag = new TagBuffer( "datalist" );
    234//              dltag.add( "id"    , "dl_" + listId );                  // inputタグとの関係付けるためのキーワード
    235                dltag.add( "id"    , listId + ".sel" );                 // inputタグとの関係付けるためのキーワード
    236
    237                dltag = getOption( dltag,value,useSelCache );
    238
    239                // キャッシュが効くと、getOption の戻り値は、null になる。
    240                if( dltag != null ) {
    241                        return intag.makeTag( row,value ) + HybsSystem.CR +
    242                                        DIV1 + dltag.makeTag( row,value ) + DIV2 + HybsSystem.CR ;
    243                }
    244                else {
    245                        return intag.makeTag( row,value ) + HybsSystem.CR ;
    246                }
    247        }
    248
    249        /**
    250         * 初期値が選択済みの 選択肢(オプション)をTagBuffer に反映します。
    251         * このオプションは、引数の値を初期値とするオプションタグ作成し、TagBuffer
    252         * に値を設定して返します。
    253         *
    254         * 第３引数は、Selection オブジェクトのキャッシュ機能を使用するかどうか指定します。
    255         * true で、使用する事を前提に、チェックを行います。
    256         * DBMENU など、他のメソッドでは、ラベル(短)の使用有無として使用しているため、異なります。
    257         *
    258         * ここでは、AAA:BBB:CCC:DDD という値を、$1,$2,$3,$4 に割り当てなおして、
    259         * QUERYを実行します。また、$1 は、本来の値として、メニューの初期値設定等に
    260         * 使用します。上記の例では、AAA が値で、それ以降は、引数になります。
    261         * さらに、元の文字列"AAA:BBB:CCC:DDD"は、$0 に割り当てられます。割り当てがない
    262         * 変数は、""(ゼロ文字列)として、扱われます。
    263         * 又、$Cには自分自身のカラム名を割り当てます。
    264         *
    265         * @param       buf    タグ文字列のバッファー
    266         * @param       value  選択されている値
    267         * @param   useSelCache Selection オブジェクトのキャッシュ機能を使用するかどうか。
    268         *
    269         * @return      オプションタグ
    270         */
    271        private TagBuffer getOption( final TagBuffer buf,final String value,final boolean useSelCache ) {
    272
    273                StringFormat format = new StringFormat( query, value, name );
    274                String newQuery = format.format();
    275                String newValue = format.getValue();
    276
    277                Selection selection = SelectionFactory.newDBSelection( newQuery, dbid, lang );
    278
    279                if( useSelCache ) {
    280                        if( selection == bkSel ) { return null; }
    281                        bkSel = selection ;
    282                }
    283
    284                buf.setBody( selection.getOption( newValue, false ) );
    285
    286                return buf;
    287        }
    288}