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     */
016    package org.opengion.plugin.io;
017    
018    import java.io.PrintWriter;
019    import java.util.List;
020    import java.util.Locale;
021    import java.util.Map ;
022    import java.util.LinkedHashMap ;
023    
024    import org.opengion.fukurou.util.HybsEntry;
025    import org.opengion.hayabusa.db.DBTableModel;
026    
027    /**
028     * TableWriter をJSON形式で出力する為の実è£?‚¯ラスですã?
029     * DefaultTableWriter を継承してã�?�¾すã?で?Œラベル?Œ名前,データの出力部のみ
030     * オーバã?ライドして?ŒJSON形式ファイルの出力機è?を実現してã�?�¾すã?
031     *
032     * 出力ã?JSON形å¼?JavaScript Object Notation)は、JavaScriptにおけã‚?
033     * オブジェクトã?表記法をベã?スとした軽量なãƒ??タ記述è¨?ªžですã?
034     * こã?クラスでは、基本çš?�«はすべてを文字å?として処ç�?�—ますã?でã€?
035     * 数字や、true,false もã?ãƒ?ƒ–ルコーãƒ??ションでくくることになりますã?
036     * ただしã?null の場合ã?、null 表記になりますがã€??常 空æ–?­?"" になるå?合もありますã?
037     * 1レコードã?みの場合でもã?配å?要ç´?�¨して取り扱ã�?�¾すã?
038     * UTF-8 でエンコードし、MIMEタイプã?application/json、拡張子ã?json とするのがä¸?ˆ¬çš?�§すã?
039     *
040     * [
041     *   { "カラãƒ?":"値1"  ,  "カラãƒ?":"値2"  , … } ,                      ?‘レコード目
042     *   { "カラãƒ?":"値1"  ,  "カラãƒ?":"値2"  , … } ,                      ?’レコード目
043     *    ・・・・ 
044     *   { "カラãƒ?":"値1"  ,  "カラãƒ?":"値2"  , … }                                ?®レコード目
045     * ]
046     *
047     * writeTableParamタグで、key="JsonName" value="パラメータå�? を指定するとã€?
048     * JSON形式でã€??列をオブジェクトとしてまとめるパラメータを指定する事が可能ですã?
049     *
050     * {
051     * パラメータå�?[
052     *   { "カラãƒ?":"値1"  ,  "カラãƒ?":"値2"  , … } ,                      ?‘レコード目
053     *   { "カラãƒ?":"値1"  ,  "カラãƒ?":"値2"  , … } ,                      ?’レコード目
054     *    ・・・・ 
055     *   { "カラãƒ?":"値1"  ,  "カラãƒ?":"値2"  , … }                                ?®レコード目
056     * ]
057     * }
058     *
059     * writeTableParamタグで、key="LowerCase" value="true" を指定するとã€?
060     * すべてのカラãƒ?‚’小文字で出力しますã??ˆデータ受信側の都合を配æ???
061     * 初期値は、false なので、基本çš?�«大æ–?­—になりますã?
062     *
063     * @og.rev 5.6.0.3 (2012/01/24) 新規作æ?
064     * @og.group ファイル出åŠ?
065     *
066     * @version  4.0
067     * @author   Kazuhiko Hasegawa
068     * @since    JDK5.0,
069     */
070    public class TableWriter_JSON extends TableWriter_Default {
071            //* こã?プログラãƒ??VERSIONæ–?­—å?を設定しますã?       {@value} */
072            private static final String VERSION = "5.6.6.1 (2013/07/12)" ;
073    
074            // 5.6.6.1 (2013/07/12) keys の整合æ?チェãƒ?‚¯を行いますã?
075            private static final Map<String,String> keysMap = new LinkedHashMap<String,String>();
076    
077            static {
078                    keysMap.put( "JSONNAME"         , "JSON形式でã€??列をオブジェクトとしてまとめる場合に使ã�?                                       );
079                    keysMap.put( "LOWERCASE"        , "カラãƒ?��(=パラメータå�?を小文字にする場合ã?true をセãƒ?ƒˆ(初期値:false)"        );
080            }
081    
082            private String  jsonName    = null;             // JSON形式でã€??列をオブジェクトとしてまとめるパラメータを指定するå?合に使ã�??
083            private boolean toLowerCase = false;    // カラãƒ?��(=パラメータå�?を小文字にする場合ã?true にセãƒ?ƒˆしますã?初期値は大æ–?­—ã?ままã€?
084    
085            /**
086             * DBTableModel から ãƒ??タを作æ?して,PrintWriter に書きå?しますã?
087             *
088             * @param       writer PrintWriterオブジェクãƒ?
089             */
090            @Override
091            public void writeDBTable( final PrintWriter writer )  {
092                    super.setHeaderSequence( "D" );
093                    super.writeDBTable( writer );
094            }
095    
096            /**
097             * PrintWriter に DBTableModelのãƒ??ブルæƒ??を書き込みますã?
098             *
099             * 出力ã?XML形式ã?、ORACLE XDK での出力ファイルと同じ形式ですã?で、直接ãƒ??タベã?スに
100             * 登録することができますã?
101             *
102             * @og.rev 5.6.0.3 (2012/01/24) JSON形式ã?フォーマットを作æ?しますã?
103             * @og.rev 5.6.1.2 (2013/02/22) jsonName もダブルクオートで囲ã�??
104             *
105             * @param       table  DBTableModelオブジェクãƒ?
106             * @param       writer PrintWriterオブジェクãƒ?
107             */
108            @Override
109            protected void writeData( final DBTableModel table,final PrintWriter writer ) {
110                    int numberOfRows =  table.getRowCount();
111    
112                    String[] names = table.getNames();
113                    if( toLowerCase ) {
114                            for( int i=0; i<names.length; i++ ) {
115    //                              names[i] = names[i].toLowerCase();                                      5.6.6.1 (2013/07/12)
116                                    names[i] = names[i].toLowerCase(Locale.JAPAN);
117                            }
118                    }
119    
120                    if( jsonName != null ) {
121                            writer.println( "{" );
122                            writer.print( "\"" );                   // 5.6.1.2 (2013/02/22) jsonName もダブルクオートで囲ã�??
123                            writer.print( jsonName );
124                            writer.print( "\":" );                  // 5.6.1.2 (2013/02/22) jsonName もダブルクオートで囲ã�??
125                    }
126    
127                    writer.println( "[" );
128    
129                    for( int row=0; row<numberOfRows; row++ ) {
130                            if( row > 0 ) { writer.print( "," ); }                       // æœ??以後ã?連結ã?ã€? を使ã�?
131                            writer.print( "{" );
132                            for( int i=0; i<numberOfColumns; i++ ) {
133                                    int clm = clmNo[i];
134                                    String val = table.getValue(row,clm);
135                                    // \(バックスラãƒ?‚·ュ) と "(ãƒ?ƒ–ルクオーãƒ?のエスケーãƒ?
136                                    if( val.contains( "\\" ) || val.contains( "\"" ) ) {
137                                            StringBuilder sb = new StringBuilder();
138                                            for( int j=0; j<val.length(); j++ ) {
139                                                    char ch = val.charAt( j );
140                                                    if( ch == '\\' || ch == '\"' ) { sb.append( '\\' ); }
141                                                    sb.append( ch );
142                                            }
143                                            val = sb.toString();
144                                    }
145    
146                                    if( i > 0 ) { writer.print( "," ); }         // æœ??以後ã?連結ã?ã€? を使ã�?
147                                    writer.print( '"' );
148                                    writer.print( names[clm] );
149                                    writer.print( "\":\"" );
150                                    writer.print( val );
151                                    writer.print( '"' );
152                            }
153                            writer.println( "}" );
154                    }
155    
156                    writer.println( "]" );
157    
158                    if( jsonName != null ) {
159                            writer.println( "}" );
160                    }
161            }
162    
163            /**
164             * パラメーターリストをセãƒ?ƒˆしますã?
165             * JSONのパラメータ名をæŒ?®šしますã?
166             * 引数がã?null の場合ã?、何もしませんã€?
167             *
168             * @og.rev 5.6.0.3 (2012/01/24) JSONのパラメータ名をæŒ?®šしますã?
169             * @og.rev 5.6.6.1 (2013/07/12) keys の整合æ?チェãƒ?‚¯を行いますã?
170             *
171             * @param       listParam       HybsEntryリスãƒ?
172             */
173            @Override
174            public void setParam( final List<HybsEntry> listParam ) {
175                    if( listParam != null && ! listParam.isEmpty() ) {
176                            for( HybsEntry entry : listParam ) {
177                                    String key = entry.getKey() ;           // 5.6.6.1 (2013/07/12) keys の整合æ?チェãƒ?‚¯
178                                    checkParam( key , keysMap );
179    
180                                    String val = entry.getValue() ;         // 5.6.6.1 (2013/07/12) val をå?に取å¾?
181                                    if( val != null && val.length() > 0 ) {
182                                            // JSON形式でã€??列をオブジェクトとしてまとめるパラメータを指定するå?合に使ã�??
183                                            if( "JsonName".equalsIgnoreCase( key ) ) {
184                                                    jsonName = val ;
185                                            }
186                                            // カラãƒ?��(=パラメータå�?を小文字にする場合ã?true にセãƒ?ƒˆしますã?初期値はfalse:大æ–?­—ã?ままã€?
187                                            else if( "LowerCase".equalsIgnoreCase( key ) ) {
188                                                    toLowerCase = Boolean.parseBoolean( val );
189                                            }
190                                    }
191    
192    //                              // JSON形式でã€??列をオブジェクトとしてまとめるパラメータを指定するå?合に使ã�??
193    //                              if( "JsonName".equalsIgnoreCase( entry.getKey() ) ) {
194    //                                      jsonName = entry.getValue();
195    //                              }
196    //                              // カラãƒ?��(=パラメータå�?を小文字にする場合ã?true にセãƒ?ƒˆしますã?初期値は大æ–?­—ã?ままã€?
197    //                              if( "LowerCase".equalsIgnoreCase( entry.getKey() ) ) {
198    //                                      toLowerCase = true;
199    //                              }
200                            }
201                    }
202            }
203    }