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.hayabusa.html;
017
018
019import java.io.IOException;
020import java.util.Map;
021
022import org.opengion.hayabusa.common.HybsSystem;
023import org.opengion.hayabusa.common.HybsSystemException;
024import org.opengion.hayabusa.db.DBColumn;
025import org.opengion.hayabusa.db.DBTableModel;
026import org.opengion.hayabusa.resource.CodeData;
027import org.opengion.hayabusa.resource.ResourceManager;
028
029import com.fasterxml.jackson.core.JsonParseException;
030import com.fasterxml.jackson.databind.JsonMappingException;
031import com.fasterxml.jackson.databind.ObjectMapper;
032
033
034
035/**
036 * JSONからテーブルモデルへの変換を行うためのAbstractクラスです。
037 * plugin.jsonの各クラスが実際の実装となります。
038 * 
039 * 内部処理的にはtableReaderと似たような形を取ります。
040 * 
041 * http://qiita.com/kenichi_nakamura/items/be73e37ec870e5845ed9
042 * https://www.mkyong.com/java/how-to-convert-java-map-to-from-json-jackson/
043 * http://www.hiihah.info/index.php?Java%EF%BC%9AJackson%E3%82%92%E3%81%A4%E3%81%8B%E3%81%A3%E3%81%A6JSON%E3%82%92%E8%AA%AD%E3%81%BF%E8%BE%BC%E3%82%80
044 *
045 * @og.group 画面表示
046 * @og.rev 5.9.21.0 (2017/6/2) 新規作成
047 *
048 * @version  4.0
049 * @author       Kazuhiko Hasegawa
050 * @since    JDK5.0,
051 */
052public abstract class AbstractJsonReader implements JsonReader {
053        protected ObjectMapper mapper = new ObjectMapper();
054        
055        private ResourceManager resource = null;
056        private int             maxRowCount     = HybsSystem.sysInt( "DB_MAX_ROW_COUNT" ) ;
057        
058        protected DBTableModel  table           = null;
059        protected DBColumn[]    dbColumn        = null;
060        
061        private int               skipRowCount  = 0;            //  データの読み飛ばし設定
062        private boolean   useRenderer   = false;        
063        
064        // 5.2.1.0 (2010/10/01) コードリソース毎のラベル逆引きマップ
065        private Map<?,?>[] maps = null;                           // ワイルドカードを指定
066
067        private boolean   useDebug      = false;                //  デバッグ情報の出力するかどうか
068        
069        /**
070         * JSON形式のテキストをパースしてMAPに変換します。
071         * keyはStringで、valueはObject型で持ちます。
072         *
073         * @return JSONをMapに分解したもの
074         */
075        @SuppressWarnings("unchecked")
076        protected Map<String, Object>  parse( final String jsonText ){
077                Map<String, Object> objmap = null;
078                try {
079                        //System.out.println(jsonText);
080                        objmap = mapper.readValue(jsonText, Map.class);
081                }
082                catch( JsonParseException ex ) {
083                        String errMsg = "パースエラー";
084                        throw new HybsSystemException( errMsg,ex );
085                }
086                catch( JsonMappingException ex ) {
087                        String errMsg = "マッピングエラー";
088                        throw new HybsSystemException( errMsg,ex );
089                }
090                catch( IOException ex ) {
091                        String errMsg = "読込みエラー";
092                        throw new HybsSystemException( errMsg,ex );
093                }
094                
095                return objmap;
096        }
097        
098        
099        /**
100         * DBColumn オブジェクトをDBTable に設定します。
101         *
102         *
103         * @param names カラム名配列
104         */
105        protected void setTableDBColumn( final String[] names ) {
106                dbColumn = new DBColumn[names.length] ;  // 3.5.4.5 追加
107                
108                // サイズ0の場合はinitする
109                if( table.getColumnCount() == 0){
110                        table.init( names.length );
111                }
112                
113                for( int i=0; i<names.length; i++ ) {
114                        DBColumn clm = resource.makeDBColumn( names[i] );
115                        table.setDBColumn( i,clm );
116                        dbColumn[i] = clm;      
117                }
118                
119                if( useRenderer ) {
120                        maps = new Map<?,?>[names.length];                //  ワイルドカードを指定
121                        for( int i=0; i<names.length; i++ ) {
122                                CodeData cd = dbColumn[i].getCodeData();
123                                if( cd != null ) { maps[i] = cd.makeLabelMap(); }
124                                else             { maps[i] = null; }
125                        }
126                }
127        }
128        
129        /**
130         * DBTableModelオブジェクトに、1行分のデータを追加します。
131         *
132         *
133         * @param values 1行分のデータ配列
134         */
135        protected void setTableColumnValues( final String[] values ) {
136                if( useRenderer ) {
137                        int clmSize = values.length;
138                        for( int clmNo=0; clmNo<clmSize; clmNo++ ) {
139                                if( maps[clmNo] != null ) {
140                                        String val = values[clmNo];
141                                        if( val == null ) { val = ""; }
142                                        else {
143                                                String tmp = (String)maps[clmNo].get( val );
144                                                if( tmp != null ) { values[clmNo] = tmp; }
145                                                else {
146                                                        int sp = val.indexOf( ':' );
147                                                        if( sp >= 0 ) {
148                                                                values[clmNo] = val.substring( 0,sp );
149                                                        }
150                                                }
151                                        }
152                                }
153                        }
154                }
155
156                table.addColumnValues( values );
157        }
158        
159        /**
160         * 内部の DBTableModel を返します。
161         *
162         * @return      テーブルモデル
163         */
164        public DBTableModel getDBTableModel() {
165                return table;
166        }
167        
168        /**
169         * リソースマネージャーをセットします。
170         * これは、言語(ロケール)に応じた DBColumn をあらかじめ設定しておく為に
171         * 必要です。
172         * リソースマネージャーが設定されていない、または、所定のキーの DBColumn が
173         * リソースに存在しない場合は、内部で DBColumn オブジェクトを作成します。
174         *
175         *
176         * @param  resource リソースマネージャー
177         */
178        public void setResourceManager( final ResourceManager resource ) {
179                this.resource = resource;
180        }
181        
182        /**
183         * DBTableModelのデータとして登録する最大件数をこの値に設定します
184         *              (初期値:DB_MAX_ROW_COUNT[={@og.value org.opengion.hayabusa.common.SystemData#DB_MAX_ROW_COUNT}])。
185         * サーバーのメモリ資源と応答時間の確保の為です。
186         *
187         * @return  最大検索件数
188         */
189        public int getMaxRowCount() {
190                return maxRowCount;
191        }
192        
193        /**
194         * DBTableModelのデータとして登録する最大件数をこの値に設定します
195         *              (初期値:DB_MAX_ROW_COUNT[={@og.value org.opengion.hayabusa.common.SystemData#DB_MAX_ROW_COUNT}])。
196         * サーバーのメモリ資源と応答時間の確保の為です。
197         *
198         * @param   maxRowCount 最大検索件数
199         */
200        public void setMaxRowCount( final int maxRowCount ) {
201                this.maxRowCount = ( maxRowCount > 0 ) ? maxRowCount : Integer.MAX_VALUE ;
202        }
203        
204        /**
205         * データの読み始めの初期値を取得します。
206         *
207         * データの読み始めの初期値を指定します。
208         * 先頭行が、0行としてカウントしますので、設定値は、読み飛ばす
209         * 件数になります。(1と指定すると、1件読み飛ばし、2行目から読み込みます。)
210         * 読み飛ばしは、コメント行などは、無視しますので、実際の行数分読み飛ばします。
211         * #NAME属性や、columns 属性は、有効です。
212         *
213         *
214         * @return      読み始めの初期値
215         */
216        public int getSkipRowCount() {
217                return skipRowCount ;
218        }
219        
220        /**
221         * データの読み飛ばし件数を設定します。
222         *
223         * @param       count 読み始めの初期値
224         */
225        public void setSkipRowCount( final int count ) {
226                skipRowCount = count;
227        }
228        
229        /**
230         * 読取処理でラベルをコードリソースに逆変換を行うかどうかを指定します。
231         *
232         *
233         * @param       useRenderer     コードリソースのラベル変換を行うかどうかを指定
234         */
235        public void setUseRenderer( final boolean useRenderer ) {
236                this.useRenderer = useRenderer;
237        }
238        
239        /**
240         * デバッグ情報を出力するかどうかを指定します。
241         *
242         *
243         * @param       useDebug        デバッグ情報を出力するかどうかを指定
244         */
245        public void setDebug( final boolean useDebug ) {
246                this.useDebug = useDebug;
247        }
248
249        /**
250         * デバッグ情報を出力するかどうかを取得します。
251         *
252         *
253         * @return      デバッグ情報を出力するかどうか(true:する/false:しない)
254         */
255        protected boolean isDebug() {
256                return useDebug ;
257        }
258        
259        /**
260         * 1行のMapデータを テーブルモデルにセットするための配列にします。
261         *
262         * names配列も与えて、その順に読みます。
263         *
264         *
265         * @return      分割された文字列配列
266         */
267        protected String[] readData( final Map<String,Object> mapdata, final String[] names ) {
268                String[] rtnData = new String[ names.length ];
269                
270                for( int i=0; i<names.length; i++){
271                        rtnData[i] = (String)mapdata.get( names[i] );
272                }
273
274                return rtnData;
275        }
276}