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.fukurou.process;
017    
018    import org.opengion.fukurou.util.Argument;
019    import org.opengion.fukurou.util.HybsEntry ;
020    import org.opengion.fukurou.xml.XSLT;
021    import org.opengion.fukurou.util.LogWriter;
022    
023    import java.util.Map ;
024    import java.util.LinkedHashMap ;
025    import java.io.File;
026    
027    /**
028     * XSLT変換結果を指定?ファイルに出力します?
029     *
030     * Process_XSLT は、AbstractProcess を継承した、ChainProcess インターフェース
031     * の実?ラスです?
032     * 上?プロセスチェインの??タは上流から渡されます?)からのLineModel の
033     * ファイルオブジェクトに対して、指定? XSL ファイルを適用して、XSL変換を行います?
034     * 出力結果は、ファイル、また? 標準?力に出力できます?
035     *
036     * 上流?ロセスでは、Name 属?として、?File』を持ち、?は、Fileオブジェク?
037     * である、Process_FileSearch を使用するのが?便利です?それ以外?クラス?
038     * 使用する場合でも?Name属?と、File オブジェクトを持つ LineModel を受け渡?
039     * できれば、使用可能です?
040     *
041     * -param_XXXX=固定? を使用して、XSLTにパラメータを設定できます?
042     *
043     * それ以外では、org.opengion.fukurou.xml.XSLT で、?力ファイル??の設定が可能に
044     * なって?為、?部??を使用するかど? -useFileInfo を指定できます?
045     * -useFileInfo=true とセ?すると、以下???目が?部?セ?されます?
046     *
047     * 入力ファイル(inXMLのフルパス)     : FILEPATH  (? G:\webapps\gf\jsp\DOC10\query.jsp)
048     * 入力親フォル?inXMLの親フォル? : ADDRESS   (? DOC10)
049     * 入力ファイル(inXMLのファイル?   : FILENAME  (? query.jsp)
050     * 入力ファイル(inXMLの更新日? )   : MODIFIED  (? yyyyMMddHHmmss形?
051     *
052     * xsl ファイルでは、xsl:param で宣?、xsl:value-of で取り出します?
053     * <xsl:param name="ADDRESS" select="" /> と宣?ておき、?な?で
054     * <xsl:value-of select="$ADDRESS"     /> とすれば、取得できます?
055     *
056     * 引数??中にスペ?スを含??合?、ダブルコー??ション("") で括って下さ??
057     * 引数??の ?』?前後には、スペ?スは挟めません。??key=value の様に
058     * 繋げてください?
059     *
060     * @og.formSample
061     *  Process_XSLT -xslfile=xslファイル -outfile=OUTFILE -append=true
062     *
063     *    -xslfile=xslファイル        ?変換を行う XSLファイル
064     *   [-outfile=出力ファイル?  ] ?変換結果の出力ファイル?
065     *   [-append=[false/true]      ] ??力ファイルを?追記す?true)か新規作?する(false)?
066     *   [-useFileInfo=[false/true] ] ??力ファイル??を?XSLTのパラメータにセ?する(true)かしな?(false)?
067     *   [-addROWSET=??ブル?    ] ???ー/フッターに ROWSET を追記します?
068     *   [-headerXX=ヘッ????  ] ??力ファイルに、??ー??を追記します?
069     *                                         添え?XX)が異なれ??のヘッ??が指定できます?
070     *   [-footerXX=フッター??  ] ??力ファイルに、フ?ー??を追記します?
071     *                                         添え?XX)が異なれ??のフッターが指定できます?
072     *   [-param_XXXX=固定?        ] ??param_SYSTEM_ID=GE
073     *                                    XSLパ?サーに対して、paramater を設定します?
074     *                                    キーが異なれ?、?のパラメータを指定できます?
075     *   [ -errAbend=[true/false]   ] ?異常発生時に、??中断(true)するか?継?false)するかを?す?初期値:true[中断する])
076     *   [ -errXmlIn=[false/true]   ] ?異常発生時に、?力ファイルに、XML形式でエラーを追記するかを指定す?初期値:false[使用しない])
077     *   [ -jspInclude=[true/false] ] ?jsp:directive.include 発見時に、そのファイル?INCLUDE するかを?す?初期値:true[使用する])
078     *   [ -display=[false/true]    ] ?結果を標準?力に表示する(true)かしな?false)?初期値:false[表示しない])
079     *   [ -debug=[false/true]      ] ?デバッグ??を標準?力に表示する(true)かしな?false)?初期値:false[表示しない])
080     *
081     * @version  4.0
082     * @author   Kazuhiko Hasegawa
083     * @since    JDK5.0,
084     */
085    public class Process_XSLT extends AbstractProcess implements ChainProcess {
086            private static final String PARAM_KEY   = "param_" ;
087            private static final String HEADER_KEY  = "header" ;
088            private static final String FOOTER_KEY  = "footer" ;
089            private static final String FILE_KEY    = "File";
090    
091            private static final String HEADER_XML    = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" ;
092            private static final String HEADER_ROWSET = "<ROWSET tableName=\"TABLENAME\">" ;
093            private static final String FOOTER_ROWSET = "</ROWSET>" ;
094    
095            private XSLT            xslt            = null ;
096            private HybsEntry[]     footerEntry     = null;
097            private String          xslfile         = null ;
098            private String          outfile         = null ;
099            private boolean         errAbend        = true;         // 中断する
100            private boolean         errXmlIn        = false;        // エラーXML形?
101            private boolean         jspInclude      = true;         // 4.2.3.0 (2008/05/26)
102            private boolean         display         = false;        // 表示しな?
103            private boolean         debug           = false;        // 5.7.3.0 (2014/02/07) ????
104    
105            private int             clmNo           = -1;
106            private int             inCount         = 0;
107            private int             errCount        = 0;
108            private String  tableName       = null;
109    
110            private static final Map<String,String> mustProparty   ;          // ?プロパティ???チェ?用 Map
111            private static final Map<String,String> usableProparty ;          // ?プロパティ?整合?チェ? Map
112    
113            static {
114                    mustProparty = new LinkedHashMap<String,String>();
115                    mustProparty.put( "xslfile",    "変換を行う XSLファイル(??)" );
116    
117                    usableProparty = new LinkedHashMap<String,String>();
118                    usableProparty.put( "outfile",          "変換結果の出力ファイル? );
119                    usableProparty.put( "append",           "出力ファイルを?追記す?true)か新規作?する(false)? );
120                    usableProparty.put( "useFileInfo",      "入力ファイル??を?XSLTのパラメータにセ?する(true)かしな?(false)? );
121                    usableProparty.put( "addROWSET" ,       "ヘッ??/フッターに ROWSET を追記します?");
122                    usableProparty.put( "header",           "出力ファイルに、??ー??を追記します?" +
123                                                                            CR + "添え?XX)が異なれ??のヘッ??が指定できます?" );
124                    usableProparty.put( "footer",           "出力ファイルに、フ?ー??を追記します?" +
125                                                                            CR + "添え?XX)が異なれ??のヘッ??が指定できます?" );
126                    usableProparty.put( "param_",           "XSLパ?サーに対して、paramater を設定します?" +
127                                                                            CR + "キーが異なれ?、?のパラメータを指定できます?" +
128                                                                            CR + "? -param_SYSTEM_ID=GE" );
129                    usableProparty.put( "errAbend", "異常発生時に、??中断(true)するか?継?false)する? +
130                                                                            CR + "(初期値:true:中断する)" );
131                    usableProparty.put( "errXmlIn", "異常発生時に、?力ファイルに、XML形式でエラーを追記するかを指定す? +
132                                                                            CR + "(初期値:false:使用しな?" );
133                    usableProparty.put( "jspInclude","jsp:directive.include 発見時に、そのファイル?INCLUDE するかを?す? +
134                                                                            CR + "(初期値:true:使用する)" );
135                    usableProparty.put( "display",  "結果を標準?力に表示する(true)かしな?false)? +
136                                                                            CR + "(初期値:false:表示しな?" );
137                    usableProparty.put( "debug",    "????を標準?力に表示する(true)かしな?false)? +
138                                                                            CR + "(初期値:false:表示しな?" );                // 5.7.3.0 (2014/02/07) ????
139            }
140    
141            /**
142             * ?ォルトコンストラクター?
143             * こ?クラスは、動??されます??ォルトコンストラクターで?
144             * super クラスに対して、?な初期化を行っておきます?
145             *
146             */
147            public Process_XSLT() {
148                    super( "org.opengion.fukurou.process.Process_XSLT",mustProparty,usableProparty );
149            }
150    
151            /**
152             * プロセスの初期化を行います?初めに??、呼び出されます?
153             * 初期処?ファイルオープン??オープン?に使用します?
154             *
155             * @og.rev 4.2.3.0 (2008/05/26) jsp:directive.include 処??実施可否を引数?します?
156             *
157             * @param   paramProcess ??タベ?スの接続???などを持って?オブジェク?
158             */
159            public void init( final ParamProcess paramProcess ) {
160                    Argument arg = getArgument();
161    
162                    xslfile                         = arg.getProparty( "xslfile" );
163                    outfile                         = arg.getProparty( "outfile" );
164                    tableName                       = arg.getProparty( "addROWSET" );
165                    boolean isAppend        = arg.getProparty( "append",false );
166                    boolean useFileInfo     = arg.getProparty( "useFileInfo",false );
167                    HybsEntry[] paramEntry  = arg.getEntrys( PARAM_KEY );           // 配?
168                    HybsEntry[] headerEntry = arg.getEntrys( HEADER_KEY );          // 配?
169                    footerEntry                     = arg.getEntrys( FOOTER_KEY );                  // 配?
170                    errAbend                        = arg.getProparty("errAbend",errAbend);
171                    errXmlIn                        = arg.getProparty("errXmlIn",errXmlIn);
172                    jspInclude                      = arg.getProparty("jspInclude",jspInclude);     // 4.2.3.0 (2008/05/26)
173                    display                         = arg.getProparty("display",display);
174                    debug                           = arg.getProparty("debug",debug);                               // 5.7.3.0 (2014/02/07) ????
175    //              if( debug ) { println( arg.toString() ); }                      // 5.7.3.0 (2014/02/07) ????
176    
177    //              File file = new File( outfile );
178                    if( outfile != null ) {
179                            File file = new File( outfile );                // 5.5.2.6 (2012/05/25) findbugs対?
180                            File dir = file.getParentFile() ;
181    
182                            // 親?レクトリを示さな??合? null 。ディレクトリが存在しな??かつ、ディレクトリが作?できな??合?処?
183                            if( dir != null && ! dir.exists() && ! dir.mkdirs() ) {
184                                    String errMsg = "?レクトリが作?できませんでした?" + dir + "]" ;
185                                    throw new RuntimeException( errMsg );
186                            }
187                    }
188                    else {
189                            // 出力?ファイル名が、指定されて????
190                            String errMsg = "outfile が指定されて?せん?;
191                            throw new RuntimeException( errMsg );
192                    }
193    
194                    xslt = new XSLT();
195    
196                    xslt.setOutFile( outfile,isAppend );
197                    xslt.setXslFile( xslfile );
198                    xslt.setParamEntry( paramEntry );
199                    xslt.useFileInfo( useFileInfo );
200                    xslt.errClose( errAbend );                      // エラー時に出力ファイルを閉じるかど??
201                    xslt.useErrXmlIn( errXmlIn );           // エラー時にXML形式で出力ファイルに追記するかど??
202                    xslt.jspInclude( jspInclude );          // 4.2.3.0 (2008/05/26) jsp:directive.include するかど?
203    
204                    if( tableName != null ) {
205                            xslt.setOutData( HEADER_XML );
206                            xslt.setOutData( HEADER_ROWSET.replace( "TABLENAME",tableName ) );
207                    }
208    
209                    int size   = headerEntry.length;
210                    for( int i=0; i<size; i++ ) {
211                            xslt.setOutData( headerEntry[i].getValue() );
212                    }
213            }
214    
215            /**
216             * 引数の LineModel を??るメソ?です?
217             * 変換処?? LineModel を返します?
218             * 後続??行わな?????タのフィルタリングを行う場?は?
219             * null ??タを返します?つまり?null ??タは、後続??行わな?
220             * フラグの代わりにも使用して?す?
221             * なお?変換処?? LineModel と、オリジナルの LineModel が?
222             * 同?、コピ?(クローン)か?、各処?ソ??決めて?す?
223             * ドキュメントに明記されて???合?、副作用が問題になる?合??
224             * ???とに自?コピ?(クローン)して下さ??
225             *
226             * @param   data        オリジナルのLineModel
227             *
228             * @return      処?換後?LineModel
229             */
230            public LineModel action( final LineModel data ) {
231                    inCount++ ;
232                    if( display ) { println( data.dataLine() ); }
233                    if( clmNo < 0 ) { clmNo = data.getColumnNo( FILE_KEY ); }
234                    File file = (File)data.getValue( clmNo );
235    
236                    if( ! file.isFile() ) { return data; }
237    
238                    String filePath = file.getPath();
239    
240                    try {
241                            if( debug ) { println( filePath ); }                    // 5.7.3.0 (2014/02/07) ????
242                            xslt.transform( filePath );
243                    }
244                    catch( RuntimeException ex ) {
245                            errCount++ ;
246                            if( errAbend ) { throw ex; }
247                            else {
248                                    logging( ex.getMessage() );
249                                    logging( "xslfile  = " + xslfile );
250                                    logging( "outfile  = " + outfile );
251                                    logging( "xmlFile  = " + filePath );
252                            }
253                    }
254    
255                    return data ;
256            }
257    
258            /**
259             * プロセスの終?行います??に??、呼び出されます?
260             * 終???ファイルクローズ??クローズ?に使用します?
261             *
262             * @param   isOK ト?タルで、OK?たかど?[true:成功/false:失敗]
263             */
264            public void end( final boolean isOK ) {
265                    if( xslt != null ) {
266                            if( isOK ) {
267                                    int size = footerEntry.length;
268                                    for( int i=0; i<size; i++ ) {
269                                            xslt.setOutData( footerEntry[i].getValue() );
270                                    }
271                                    if( tableName != null ) {
272                                            xslt.setOutData( FOOTER_ROWSET );
273                                    }
274                            }
275                            xslt.close();
276                    }
277            }
278    
279            /**
280             * プロセスの処?果のレポ?ト表現を返します?
281             * 処??ログラ?、?力件数、?力件数などの??です?
282             * こ???をそのまま、標準?力に出すことで、結果レポ?トと出来るよ?
283             * 形式で出してください?
284             *
285             * @return   処?果のレポ??
286             */
287            public String report() {
288                    String report = "[" + getClass().getName() + "]" + CR
289                                    + TAB + "XSL File   : " + xslfile   + CR
290                                    + TAB + "OUT File   : " + outfile   + CR
291                                    + TAB + "Table Name : " + tableName + CR
292                                    + TAB + "File Count : " + inCount   + CR
293                                    + TAB + "Err  Count : " + errCount ;
294    
295                    return report ;
296            }
297    
298            /**
299             * こ?クラスの使用方法を返します?
300             *
301             * @return      こ?クラスの使用方?
302             */
303            public String usage() {
304                    StringBuilder buf = new StringBuilder();
305    
306                    buf.append( "XSLT変換結果を指定?ファイルに出力します?"                                                                       ).append( CR );
307                    buf.append( CR );
308                    buf.append( "Process_XSLT は、AbstractProcess を継承した、ChainProcess インターフェース"     ).append( CR );
309                    buf.append( "の実?ラスです?"                                                                                                                  ).append( CR );
310                    buf.append( "上?プロセスチェインの??タは上流から渡されます?)からのLineModel の"            ).append( CR );
311                    buf.append( "ファイルオブジェクトに対して、指定? XSL ファイルを適用して、XSL変換?                ).append( CR );
312                    buf.append( "行います?出力結果は、ファイル、また? 標準?力に出力できます?"                              ).append( CR );
313                    buf.append( CR );
314                    buf.append( "上流?ロセスでは、Name 属?として、?File』を持ち、?は、Fileオブジェク?            ).append( CR );
315                    buf.append( "である、Process_FileSearch を使用するのが?便利です?それ以外?クラス?           ).append( CR );
316                    buf.append( "使用する場合でも?Name属?と、File オブジェクトを持つ LineModel を受け渡?  ).append( CR );
317                    buf.append( "できれば、使用可能です?"                                                                                                            ).append( CR );
318                    buf.append( CR );
319                    buf.append( "-param_XXXX=固定? を使用して、XSLTにパラメータを設定できます?"                          ).append( CR );
320                    buf.append( CR );
321                    buf.append( "それ以外では、org.opengion.fukurou.xml.XSLT で、?力ファイル??の設定が可能に"           ).append( CR );
322                    buf.append( "なって?為、?部??を使用するかど? -useFileInfo を指定できます?"              ).append( CR );
323                    buf.append( "-useFileInfo=true とセ?すると、以下???目が?部?セ?されます?"           ).append( CR );
324                    buf.append( CR );
325                    buf.append( "入力ファイル(inXMLのフルパス)     : FILEPATH  (? G:/temp/DOC10/query.jsp)"   ).append( CR );
326                    buf.append( "入力親フォル?inXMLの親フォル? : ADDRESS   (? DOC10)"                                              ).append( CR );
327                    buf.append( "入力ファイル(inXMLのファイル?   : FILENAME  (? query.jsp)"                                 ).append( CR );
328                    buf.append( "入力ファイル(inXMLの更新日? )   : MODIFIED  (? yyyyMMddHHmmss形?"                ).append( CR );
329                    buf.append( CR );
330                    buf.append( "xsl ファイルでは、xsl:param で宣?、xsl:value-of で取り出します?"                      ).append( CR );
331                    buf.append( "<xsl:param name=\"ADDRESS\" select=\"\" /> と宣?ておき、?な?で"         ).append( CR );
332                    buf.append( "<xsl:value-of select=\"$ADDRESS\"     /> とすれば、取得できます?"                                ).append( CR );
333                    buf.append( CR );
334                    buf.append( "引数??中に空白を含??合?、ダブルコー??ション(\"\") で括って下さ??" ).append( CR );
335                    buf.append( "引数??の ?』?前後には、空白は挟めません。??key=value の様に"             ).append( CR );
336                    buf.append( "繋げてください?                                                                                                                              ).append( CR );
337                    buf.append( CR ).append( CR );
338    
339                    buf.append( getArgument().usage() ).append( CR );
340    
341                    return buf.toString();
342            }
343    
344            /**
345             * こ?クラスは、main メソ?から実行できません?
346             *
347             * @param       args    コマンド引数配?
348             */
349            public static void main( final String[] args ) {
350                    LogWriter.log( new Process_XSLT().usage() );
351            }
352    }