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    }