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.Map ;
021    import java.util.LinkedHashMap ;
022    
023    import org.opengion.fukurou.util.HybsEntry;
024    import org.opengion.fukurou.util.StringUtil;
025    import org.opengion.hayabusa.common.HybsSystem;
026    import org.opengion.hayabusa.db.DBTableModel;
027    
028    /**
029     * TableWriter をXML形式で出力する為の実è£?‚¯ラスですã?
030     * DefaultTableWriter を継承してã�?�¾すã?で?Œラベル?Œ名前,データの出力部のみ
031     * オーバã?ライドして?ŒXML形式ファイルの出力機è?を実現してã�?�¾すã?
032     *
033     * 出力ã?XML形式ã?、拡張オラクル ?¸?¤?«形式ã??¸?­?¬ファイルですã?
034     * オラクル?¸?¤?«形式ã??¸?­?¬とは、下記ã?ような ROWSET をトãƒ??とする ROW の
035     * é›?�¾りで?‘レコードを表しã?各ROWには、カラãƒ?��をキーとするXMLになってã�?�¾すã?
036     *
037     *   <ROWSET>
038     *       <ROW num="1">
039     *           <カラãƒ?>値1</カラãƒ?>
040     *             ?¥?¥?¥
041     *           <カラãƒ?>値n</カラãƒ?>
042     *       </ROW>
043     *        ?¥?¥?¥
044     *       <ROW num="n">
045     *          ?¥?¥?¥
046     *       </ROW>
047     *   <ROWSET>
048     *
049     * こã?形式であれば、XDK(Oracle XML Developer's Kit)を利用すればã€?�ž常に簡単に
050     * ãƒ??タベã?スとXMLファイルとの交換が可能ですã?
051     * <a href="http://otn.oracle.co.jp/software/tech/xml/xdk/index.html" target="_blank" >
052     * XDK(Oracle XML Developer's Kit)</a>
053     *
054     * 拡張?¸?¤?«形式とは、ROW 以外に、SQL処ç�?”¨タグ(EXEC_SQL)を持つ XML ファイルですã?
055     * これは、オラクルXDKで処ç�?�™るå?合ã?無視されますã?で、同様に扱ã�?�“とがå?来ますã?
056     * こã?、EXEC_SQL は、それそれã? XMLãƒ??タをデータベã?スに登録する際にã€?
057     * SQL処ç�?‚’自動的に流す為の、SQLæ–?‚’記載しますã?
058     * こã?処ç�??、イベント毎に実行される為、その配置é ??重要ですã?
059     * こã?タグは、è¤?•°記述することもå?来ますが、BODY部にはã€?¼‘つのSQLæ–??み記述しますã?
060     *
061     *   &lt;ROWSET tablename="GEXX" &gt;
062     *       &lt;EXEC_SQL&gt;                    æœ??に記載して、å?期å?ç�?ãƒ??タクリアç­?を実行させるã€?
063     *           delete from GEXX where YYYYY
064     *       &lt;/EXEC_SQL&gt;
065     *       &lt;MERGE_SQL&gt;                   こã?SQLæ–?�§ UPDATEして、結果が0件ならINSERTを行いますã?
066     *           update GEXX set AA=[AA] , BB=[BB] where CC=[CC]
067     *       &lt;/MERGE_SQL&gt;
068     *       &lt;ROW num="1"&gt;
069     *           &lt;カラãƒ?&gt;値1&lt;/カラãƒ?&gt;
070     *             ?¥?¥?¥
071     *           &lt;カラãƒ?&gt;値n&lt;/カラãƒ?&gt;
072     *       &lt;/ROW&gt;
073     *        ?¥?¥?¥
074     *       &lt;ROW num="n"&gt;
075     *          ?¥?¥?¥
076     *       &lt;/ROW&gt;
077     *       &lt;EXEC_SQL&gt;                    æœ?¾Œに記載してã€??目の設å®?整合æ?登録)を行うã€?
078     *           update GEXX set AA='XX' , BB='XX' where YYYYY
079     *       &lt;/EXEC_SQL&gt;
080     *   &lt;ROWSET&gt;
081     *
082     * @og.group ファイル出åŠ?
083     *
084     * @version  4.0
085     * @author   Kazuhiko Hasegawa
086     * @since    JDK5.0,
087     */
088    public class TableWriter_XML extends TableWriter_Default {
089            //* こã?プログラãƒ??VERSIONæ–?­—å?を設定しますã?       {@value} */
090            private static final String VERSION = "5.6.7.0 (2013/07/27)" ;
091    
092            // 5.6.6.1 (2013/07/12) keys の整合æ?チェãƒ?‚¯を行いますã?
093            private static final Map<String,String> keysMap = new LinkedHashMap<String,String>();
094    
095            static {
096                    keysMap.put( "TABLENAME"        , "処ç�?‚’実施するãƒ??ブル名をæŒ?®?                                                                                             );
097                    keysMap.put( "FIRST"            , "æœ??に記載して、å?期å?ç�?ãƒ??タクリアç­?を実行させる、EXEC_SQLを指å®?            );
098                    keysMap.put( "LAST"                     , "æœ?¾Œに記載してã€??目の設å®?整合æ?登録)を行う、EXEC_SQLを指å®?                         );
099                    keysMap.put( "MERGESQL"         , "こã?SQLæ–?�§ UPDATEして、結果が0件ならINSERTを行う、MERGE_SQLを指å®?                  );
100            }
101    
102            private String  tableName               = "" ;          // 4.0.0 (2005/01/31)
103            private String  firstExecSql    = "" ;          // 4.0.0 (2005/01/31)
104            private String  lastExecSql             = "" ;          // 4.0.0 (2005/01/31)
105    
106            private String  mergeSql                = "" ;          // 5.6.6.1 (2013/07/12) MERGE_SQL 対å¿?
107    
108    //      /**
109    //       * ãƒ?ƒ•ォルトコンストラクター
110    //       *
111    //       */
112    //      public TableWriter_XML() {
113    //              super();
114    //      }
115    
116            /**
117             * DBTableModel から ãƒ??タを作æ?して,PrintWriter に書きå?しますã?
118             *
119             * @og.rev 3.1.1.0 (2003/03/28) 同期メソãƒ?ƒ‰(synchronized付き)を非同期に変更するã€?
120             * @og.rev 3.5.4.3 (2004/01/05) 引数に PrintWriter を受け取るよã�?�«変更しますã?
121             *
122             * @param       writer PrintWriterオブジェクãƒ?
123             */
124            @Override
125            public void writeDBTable( final PrintWriter writer )  {
126                    super.setHeaderSequence( "D" );
127                    super.writeDBTable( writer );
128            }
129    
130            /**
131             * PrintWriter に DBTableModelのヘッãƒ??æƒ??を書き込みますã?
132             * XML のヘッãƒ??はã€?lt;?xml version='1.0' encoding='encode値'?&gt; になりますã?
133             * encoding属æ?には、encode値をセãƒ?ƒˆしますã?
134             * encoding属æ?に設定できる値はã€?UTF-8","UTF-16","Shift_JIS" ですã?
135             *
136             * @og.rev 3.1.1.0 (2003/03/28) 同期メソãƒ?ƒ‰(synchronized付き)を非同期に変更するã€?
137             * @og.rev 4.0.0.0 (2005/01/31) XML宣è¨?ƒ¨のencoding属æ?をã?encode値をセãƒ?ƒˆするã€?
138             *
139             * @param       writer PrintWriterオブジェクãƒ?
140             */
141            @Override
142            protected void writeHeader( final PrintWriter writer ) {
143                    String encoding = getEncode();
144                    writer.println( "<?xml version='1.0' encoding='" + encoding + "'?>" ) ;
145            }
146    
147            /**
148             * PrintWriter に DBTableModelのãƒ??ブルæƒ??を書き込みますã?
149             *
150             * 出力ã?XML形式ã?、ORACLE XDK での出力ファイルと同じ形式ですã?で、直接ãƒ??タベã?スに
151             * 登録することができますã?
152             *
153             * @og.rev 3.1.1.0 (2003/03/28) 同期メソãƒ?ƒ‰(synchronized付き)を非同期に変更するã€?
154             * @og.rev 3.8.0.1 (2005/06/17) DBTypeã�?NVAR の場合ã?、å?のUnicodeに戻しますã?
155             * @og.rev 4.0.0.0 (2005/01/31) EXEC_SQL タグ機è?の追åŠ?
156             * @og.rev 5.1.6.0 (2010/05/01) DbType の初期値(dbType)を利用するã€?
157             * @og.rev 5.2.1.0 (2010/10/01) useRenderer 対å¿?
158             * @og.rev 5.6.6.1 (2013/07/12) MERGE_SQL 対å¿?
159             * @og.rev 5.6.7.0 (2013/07/27) 改行å?ç�??見直ã�?
160             *
161             * @param       table  DBTableModelオブジェクãƒ?
162             * @param       writer PrintWriterオブジェクãƒ?
163             */
164            @Override
165            protected void writeData( final DBTableModel table,final PrintWriter writer ) {
166                    int numberOfRows =  table.getRowCount();
167                    boolean useRenderer = isUseRenderer();  // 5.2.1.0 (2010/10/01)
168    
169                    writer.print( "<ROWSET" );
170                    writer.print( tableName );
171                    writer.println( ">" );
172    
173                    // 4.0.0 (2005/01/31)
174    //              writer.println( firstExecSql );
175                    writer.print( firstExecSql );                           // 5.6.7.0 (2013/07/27) 改行å?ç�??見直ã�?
176    
177                    // 5.6.6.1 (2013/07/12) MERGE_SQL 対å¿?
178    //              writer.println( mergeSql );
179                    writer.print( mergeSql );                                       // 5.6.7.0 (2013/07/27) 改行å?ç�??見直ã�?
180    
181                    for( int row=0; row<numberOfRows; row++ ) {
182                            writer.print( "<ROW num=\"" );
183                            writer.print( row+1 );
184                            writer.println( "\">" );
185                            for( int i=0; i<numberOfColumns; i++ ) {
186                                    int clm = clmNo[i];
187                                    String val = table.getValue(row,clm);
188    //                              if( "NVAR".equals( dbColumn[clm].getDbType()) ) {
189                                    if( dbType[i] == NVAR ) {
190                                            val = StringUtil.getReplaceEscape( val );
191                                    }
192                                    // 5.2.1.0 (2010/10/01) useRenderer 対å¿?
193                                    else if( useRenderer ) {
194                                            val = StringUtil.spanCut( dbColumn[clm].getRendererValue( val ) );
195                                    }
196    
197                                    writer.print( "<" );
198                                    writer.print( table.getColumnName(clm) );
199                                    writer.print( ">" );
200                                    writer.print( StringUtil.htmlFilter( val ) );
201                                    writer.print( "</" );
202                                    writer.print( table.getColumnName(clm) );
203                                    writer.println( ">" );
204                            }
205                            writer.println( "</ROW>" );
206                    }
207    
208                    // 4.0.0 (2005/01/31)
209    //              writer.println( lastExecSql );
210                    writer.print( lastExecSql );                            // 5.6.7.0 (2013/07/27) 改行å?ç�??見直ã�?
211                    writer.println( "</ROWSET>" );
212            }
213    
214            /**
215             * パラメーターリストをセãƒ?ƒˆしますã?
216             * å†?ƒ¨は、HybsEntry クラスを持ってã�?�¾すã?
217             * 引数がã?null の場合ã?、何もしませんã€?
218             *
219             * @og.rev 4.0.0.0 (2005/01/31) 新規追åŠ?
220             * @og.rev 5.6.6.1 (2013/07/12) MERGE_SQL 対å¿?
221             * @og.rev 5.6.6.1 (2013/07/12) keys の整合æ?チェãƒ?‚¯を行いますã?
222             *
223             * @param       listParam       HybsEntryリスãƒ?
224             */
225            @Override
226            public void setParam( final List<HybsEntry> listParam ) {
227                    if( listParam != null && ! listParam.isEmpty() ) {
228                            StringBuilder first = new StringBuilder() ;
229                            StringBuilder last  = new StringBuilder() ;
230                            StringBuilder merge = new StringBuilder() ;             // 5.6.6.1 (2013/07/12) MERGE_SQL 対å¿?
231    
232                            for( HybsEntry entry : listParam ) {
233                                    String key = entry.getKey() ;           // 5.6.6.1 (2013/07/12) keys の整合æ?チェãƒ?‚¯
234                                    checkParam( key , keysMap );
235    
236                                    String val = entry.getValue() ;         // 5.6.6.1 (2013/07/12) val をå?に取å¾?
237                                    if( val != null && val.length() > 0 ) {
238                                            // 処ç�?‚’実施するãƒ??ブル名をæŒ?®?
239                                            // è¤?•°の key="TableName" があれã?、最後ã?みが有効ã€?
240                                            if( "TableName".equalsIgnoreCase( key ) ) {
241                                                    tableName = " tableName=\"" + val + "\"" ;
242                                            }
243                                            // æœ??に記載して、å?期å?ç�?ãƒ??タクリアç­?を実行させる、EXEC_SQLを指å®?
244                                            else if( "First".equalsIgnoreCase( key ) ) {
245                                                    first.append( "<EXEC_SQL>" );
246                                                    first.append( StringUtil.htmlFilter( val ) );
247                                                    first.append( "</EXEC_SQL>" );
248                                                    first.append( HybsSystem.CR );
249                                            }
250                                            // æœ?¾Œに記載してã€??目の設å®?整合æ?登録)を行う、EXEC_SQLを指å®?
251                                            else if( "Last".equalsIgnoreCase( key ) ) {
252                                                    last.append( "<EXEC_SQL>" );
253                                                    last.append( StringUtil.htmlFilter( val ) );
254                                                    last.append( "</EXEC_SQL>" );
255                                                    last.append( HybsSystem.CR );
256                                            }
257                                            // こã?SQLæ–?�§ UPDATEして、結果が0件ならINSERTを行う、MERGE_SQLを指å®?
258                                            else if( "MergeSql".equalsIgnoreCase( key ) ) {
259                                                    merge.append( "<MERGE_SQL>" );
260                                                    merge.append( StringUtil.htmlFilter( val ) );
261                                                    merge.append( "</MERGE_SQL>" );
262                                                    merge.append( HybsSystem.CR );
263                                            }
264                                    }
265                            }
266                            firstExecSql = first.toString();
267                            lastExecSql  = last.toString();
268                            mergeSql     = merge.toString();                // 5.6.6.1 (2013/07/12) MERGE_SQL 対å¿?
269                    }
270    
271    //                      HybsEntry[] entries = listParam.toArray( new HybsEntry[listParam.size()] );
272    //                      for( int i=0; i<entries.length; i++ ) {
273    //                              String key = entries[i].getKey();
274    //                              String val = entries[i].getValue();
275    //                              if( "First".equalsIgnoreCase( key ) ) {
276    //                                      first.append( "<EXEC_SQL>" );
277    //                                      first.append( StringUtil.htmlFilter( val ) );
278    //                                      first.append( "</EXEC_SQL>" );
279    //                                      first.append( HybsSystem.CR );
280    //                              }
281    //                              else if( "Last".equalsIgnoreCase( key ) ) {
282    //                                      last.append( "<EXEC_SQL>" );
283    //                                      last.append( StringUtil.htmlFilter( val ) );
284    //                                      last.append( "</EXEC_SQL>" );
285    //                                      last.append( HybsSystem.CR );
286    //                              }
287    //                              // 5.6.6.1 (2013/07/12) MERGE_SQL 対å¿?
288    //                              else if( "MergeSql".equalsIgnoreCase( key ) ) {
289    //                                      merge.append( "<MERGE_SQL>" );
290    //                                      merge.append( StringUtil.htmlFilter( val ) );
291    //                                      merge.append( "</MERGE_SQL>" );
292    //                                      merge.append( HybsSystem.CR );
293    //                              }
294    //                              // è¤?•°の TableName があれã?、最後ã?みが有効ã€?チェãƒ?‚¯なã�?
295    //                              else if( "TableName".equalsIgnoreCase( key )
296    //                                                      && val != null && val.length() > 0 ) {
297    //                                      tableName = " tableName=\"" + val + "\"" ;
298    //                              }
299    //                      }
300    //                      firstExecSql = first.toString();
301    //                      lastExecSql  = last.toString();
302    //                      mergeSql     = merge.toString();                // 5.6.6.1 (2013/07/12) MERGE_SQL 対å¿?
303    //              }
304            }
305    }