    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.view;
    017
    018import org.opengion.fukurou.util.StringUtil;
    019import org.opengion.hayabusa.html.AbstractViewForm;
    020import org.opengion.hayabusa.html.ViewJsonParam;
    021
    022/**
    023 * 検索結果を自動的に表形式に変換する、テーブル作成クラスです。
    024 *
    025 * ユーザー単位に表示するカラムの順番、表示可非を指定できるように対応します。
    026 * setColumnDisplay( final String columnName ) に、指定された順番に
    027 * 表示するというHTMLFormatTable の簡易版として用意します。
    028 * 各HTMLのタグに必要な setter/getterメソッドのみ，追加定義しています。
    029 *
    030 * AbstractViewForm を継承している為,ロケールに応じたラベルを出力させる事が出来ます。
    031 *
    032 * @og.group 画面表示
    033 * @og.rev 5.1.7.0 (2016/04/01) 新規作成
    034 *
    035 * @version  5.0
    036 * @author       Takahashi Masakazu
    037 * @since    JDK5.0,
    038 */
    039public class ViewForm_JSON extends AbstractViewForm {
    040        //* このプログラムのVERSION文字列を設定します。   {@value} */
    041        private static final String VERSION = "6.8.3.1 (2017/12/01)" ;
    042
    043        private int             clmCnt          = -1;
    044
    045//      private String  viewClms        ;       // 6.9.8.0 (2018/05/28) FindBugs:書き込まれていないフィールド
    046
    047        private String dataName;
    048        private boolean useHead;
    049        private boolean useInfo;
    050        private boolean useRenderer;
    051        private boolean useNullOmit;    // 6.7.7.0 (2017/03/31)
    052        private boolean useZeroOmit;    // 6.7.7.0 (2017/03/31)
    053        private boolean useEqValOmit;   // 6.8.3.0 (2017/11/27)
    054        // private boolean useUtfEncode;        // '\u0000'形式への変換は仕様上必須ではないので現時点では実装しない
    055
    056        private String rendererCols;    // 5.9.27.0 (2017/12/01)
    057
    058        /** ヘッダー部分のキャッシュ変数 */
    059        protected String        headerLine;
    060
    061        /**
    062         * デフォルトコンストラクター
    063         *
    064         * @og.rev 6.4.9.1 (2016/08/05) Each class should declare at least one constructor
    065         */
    066        public ViewForm_JSON() { super(); }             // これも、自動的に呼ばれるが、空のメソッドを作成すると警告されるので、明示的にしておきます。
    067
    068        /**
    069         * DBTableModel から HTML文字列を作成して返します。
    070         * startNo(表示開始位置)から、pageSize(表示件数)までのView文字列を作成します。
    071         * 表示残りデータが pageSize 以下の場合は,残りのデータをすべて出力します。
    072         *
    073         * @og.rev 5.5.4.2 (2012/07/13) editName指定時の編集対応
    074         * @og.rev 6.8.3.0 (2017/11/27) 処理速度向上(カラムのキャッシュ)と、同一値のomit処理(useEqValOmit)。
    075         * @og.rev 6.8.3.1 (2017/12/01) nullの場合、useNullOmit || useZeroOmit と、useEqValOmit の useRenderer 対応
    076         * @og.rev 5.9.17.0 (2017/12/01) レンデラー利用カラム追加
    077         *
    078         * @param  startNo        表示開始位置
    079         * @param  pageSize   表示件数
    080         *
    081         * @return      DBTableModelから作成された HTML文字列
    082         */
    083        @Override
    084        public String create( final int startNo, final int pageSize )  {
    085                //if( getRowCount() == 0 ) { return ""; }       // 暫定処置
    086
    087                paramInit();
    088
    089                // 5.9.27.0 (2017/12/01) レンデラー利用カラムの指定（JSONのみの特殊判定）
    090                final boolean[] rendCols = new boolean[clmCnt];
    091        //      Arrays.fill( rendCols ,false );
    092                setBooleanArray( rendererCols,true,rendCols );
    093
    094                headerLine       = null;
    095                final int lastNo = getLastNo( startNo, pageSize );
    096
    097                final StringBuilder out = new StringBuilder( BUFFER_LARGE );
    098
    099                // 6.8.3.0 (2017/11/27) 処理速度向上(カラムのキャッシュ)
    100                final String[] clms    = new String[clmCnt];
    101                final String[] oldDiff = new String[clmCnt];            // 6.8.3.1 (2017/12/01) 一つ前と比較するための変数
    102                final String[] oldVals = new String[clmCnt];            // useRenderer が加味された値
    103                for(int clm = 0; clm < clmCnt; clm++) {
    104                        clms[clm] = "\"" + getColumnName( clm ) + "\":\"" ;
    105                }
    106
    107                //JSON開始
    108                out.append( '{' ).append( CR );
    109
    110                int rowcnt = 0;
    111                out.append( '"' ).append( dataName ).append( "\":[" );
    112                for( int row=startNo; row<lastNo; row++ ) {
    113                        if( isSkip( row ) || isSkipNoEdit( row ) ) { continue; }
    114                        if(rowcnt > 0 ){ out.append( ',' ); }
    115                        rowcnt++;
    116                        out.append( '{' );
    117
    118                        int clmcount = 0;
    119                        for(int clm = 0; clm < clmCnt; clm++) {
    120
    121                                if( isColumnDisplay( clm ) ) {                                          // 6.8.3.0 (2017/11/27) continue 処理を囲う形で前に持ってきます。
    122                                        // 6.7.7.0 (2017/03/31)
    123                                        final String val = getValue( row,clm );
    124
    125                                        if( ( val == null || val.isEmpty() ) && ( useNullOmit || useZeroOmit ) ||
    126                                                ( "0".equals( val ) || "0.0".equals( val ) || "0.00".equals( val ) ) && useZeroOmit ||
    127                                                val.equals( oldDiff[clm] ) && useEqValOmit ) { continue; }              // 6.8.3.0 (2017/11/27) 同一値のomit処理(useEqValOmit) 追加
    128
    129                                        oldDiff[clm] = val;                                                                                                     // 6.8.3.0 (2017/11/27) 同一値のomit処理(useEqValOmit) 追加
    130                                        oldVals[clm] = StringUtil.jsonFilter(                                                           // 6.8.3.1 (2017/12/01)
    131                                                                                useRenderer || rendCols[clm] ? getValueLabel(row,clm) : val             // 5.9.27.0 (2017/12/01)
    132                                                                        );
    133
    134                                        if( clmcount > 0 ){ out.append( ',' );}
    135                                        clmcount++;
    136
    137                                        out.append( clms[clm] )                                                                                         // 6.8.3.1 (2017/12/01)
    138                                                .append( oldVals[clm] )
    139                                                .append( '"' );
    140                                }
    141                        }
    142                        out.append( '}' );
    143                }
    144
    145                // 6.8.3.0 (2017/11/27) 同一値のomit処理(useEqValOmit) 追加の後処理
    146                if( useEqValOmit ) {
    147                        out.append( ",{" );
    148                        int clmcount = 0;
    149                        for(int clm = 0; clm < clmCnt; clm++) {
    150                                if( isColumnDisplay( clm ) ) {
    151                                        if( clmcount > 0 ){ out.append( ',' );}
    152                                        clmcount++;
    153                                        out.append( clms[clm] )
    154                                                .append( oldVals[clm] )
    155                                                .append( '"' );
    156                                }
    157                        }
    158                        out.append( '}' );
    159                }
    160
    161                out.append( ']' ).append( CR );
    162
    163                if( useHead ){
    164                        out.append( ',' ).append( getHeader() ).append( CR );
    165                }
    166                if( useInfo ){
    167                        out.append( ',' ).append( getInfo(rowcnt) ).append( CR );
    168                }
    169
    170                //JSON終わり
    171                out.append( '}' ).append( CR );
    172
    173                return out.toString();
    174        }
    175
    176        /**
    177         * パラメータ内容を初期化します。
    178         *
    179         * @og.rev 6.7.7.0 (2017/03/31) ViewJsonParam属性を、文字列から、boolean に変更
    180         * @og.rev 6.8.3.0 (2017/11/27) useEqValOmit属性の追加
    181         * @og.rev 5.9.17.0 (2017/12/01) レンデラー利用カラム追加
    182         *
    183         */
    184        private void paramInit() {
    185                dataName        = getParam( ViewJsonParam.JSON_DATANAME_KEY     , ViewJsonParam.JSON_DATANAME           );
    186                useHead         = StringUtil.nval( getParam( ViewJsonParam.JSON_HEAD_KEY                        ) , ViewJsonParam.USE_JSON_HEAD         );
    187                useInfo         = StringUtil.nval( getParam( ViewJsonParam.JSON_INFO_KEY                        ) , ViewJsonParam.USE_JSON_INFO         );
    188                useRenderer     = StringUtil.nval( getParam( ViewJsonParam.JSON_RENDERER_KEY            ) , ViewJsonParam.USE_JSON_RENDERER     );
    189                useNullOmit     = StringUtil.nval( getParam( ViewJsonParam.JSON_NULLOMIT_KEY            ) , ViewJsonParam.USE_JSON_NULLOMIT     );      // 6.7.7.0 (2017/03/31)
    190                useZeroOmit     = StringUtil.nval( getParam( ViewJsonParam.JSON_ZEROOMIT_KEY            ) , ViewJsonParam.USE_JSON_ZEROOMIT     );      // 6.7.7.0 (2017/03/31)
    191                useEqValOmit= StringUtil.nval( getParam( ViewJsonParam.JSON_EQVALOMIT_KEY               ) , ViewJsonParam.USE_JSON_EQVALOMIT);  // 6.8.3.0 (2017/11/27)
    192        //      useUtfEncode= StringUtil.nval( getParam( ViewJsonParam.JSON_UTF_ENCODE                  ) , ViewJsonParam.USE_JSON_UTFENC       );
    193
    194                rendererCols= getParam( ViewJsonParam.JSON_RENDERER_COLS_KEY , ViewJsonParam.JSON_RENDERER_COLS );                                              // 5.9.17.0 (2017/12/01)
    195
    196                clmCnt = getColumnCount();
    197        }
    198
    199        /**
    200         * DBTableModel から テーブルのヘッダータグ文字列を作成して返します。
    201         *
    202         *
    203         * @return      テーブルのヘッダータグ文字列
    204         */
    205        protected String getHeader() {
    206                return "\"HEAD\":{" + getTableHead() + "}";
    207        }
    208
    209        /**
    210         * DBTableModel から テーブルのタグ文字列を作成して返します。
    211         *
    212         *
    213         * @return      テーブルのタグ文字列
    214         */
    215        protected String getTableHead() {
    216                return getHeadLine();
    217        }
    218
    219        /**
    220         * ヘッダー繰り返し部を、getTableHead()メソッドから分離。
    221         *
    222         *
    223         * @return      テーブルのタグ文字列
    224         */
    225        protected String getHeadLine() {
    226                if( headerLine != null ) { return headerLine; }         // キャッシュを返す。
    227
    228                final StringBuilder buf = new StringBuilder( BUFFER_MIDDLE );
    229
    230                for(int clm = 0; clm < clmCnt; clm++) {
    231                        if( isColumnDisplay( clm ) ) {
    232                                if( buf.length() > 0 ){ buf.append( ',' ); }
    233                                buf.append( '"' )
    234                                        .append( getColumnName( clm ) )
    235                                        .append( "\":\"" )
    236                                        .append( StringUtil.jsonFilter( getColumnLabel( clm ) ) )
    237                                        .append(  '"' );
    238                        }
    239                }
    240
    241                headerLine = buf.toString();
    242                return headerLine;
    243        }
    244
    245        /**
    246         * DBTableModel から テーブルのヘッダータグ文字列を作成して返します。
    247         *
    248         * @param       rowcount 行番号
    249         *
    250         * @return      テーブルのヘッダータグ文字列
    251         */
    252        protected String getInfo( final int rowcount ) {
    253                return new StringBuilder( BUFFER_MIDDLE )
    254                                                .append( "\"INFO\":{\"COUNT\":\"" )
    255                                                .append( rowcount )
    256                                                .append( "\"}")
    257                                                .toString();
    258        }
    259
    260//      /**
    261//       * ビューで表示したカラムの一覧をCSV形式で返します。
    262//       *
    263//       * @og.rev 5.1.6.0 (2010/05/01) 新規追加
    264//       * @og.rev 5.8.6.0 (2015/04/03) オリジナルカラム対応
    265//       * @og.rev 6.9.8.0 (2018/05/28) FindBugs:書き込まれていないフィールド
    266//       *
    267//       * @return      ビューで表示したカラムの一覧
    268//       */
    269//      @Override
    270//      public String getViewClms() {
    271//              // 一旦、削除しておきます。
    272//              if( viewClms == null ) { return super.getViewClms(); }
    273//              return viewClms;
    274//      }
    275
    276        /**
    277         * フォーマットメソッドを使用できるかどうかを問い合わせます。
    278         *
    279         * @return  使用可能(true)/ 使用不可能(false)
    280         */
    281        public boolean canUseFormat() {
    282                return false;
    283        }
    284}