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.xml; 017 018 import org.xml.sax.InputSource; 019 import org.xml.sax.SAXException; 020 import org.xml.sax.Attributes; 021 import org.xml.sax.helpers.DefaultHandler; 022 023 import javax.xml.parsers.SAXParserFactory; 024 import javax.xml.parsers.SAXParser; 025 import javax.xml.parsers.ParserConfigurationException; 026 027 import java.io.Reader; 028 import java.io.IOException; 029 import java.util.Map; 030 031 /** 032 * ã“ã?クラスã¯ã€æ‹¡å¼µã‚ªãƒ©ã‚¯ãƒ« XDKå½¢å¼ã?XMLファイルをå?ç?™ã‚‹ãƒãƒ³ãƒ‰ãƒ©ã§ã™ã? 033 * オラクルXDKå½¢å¼ã?XMLã¨ã¯ã€ä¸‹è¨˜ã?よã†ãª ROWSET をトãƒ??ã¨ã™ã‚‹ ROW ã® 034 * é›?¾ã‚Šã§?‘レコードを表ã—ã?å„ROWã«ã¯ã€ã‚«ãƒ©ãƒ?ã‚’ã‚ーã¨ã™ã‚‹XMLã«ãªã£ã¦ã?¾ã™ã? 035 * 036 * <ROWSET> 037 * <ROW num="1"> 038 * <カラãƒ?>値1</カラãƒ?> 039 * ?¥?¥?¥ 040 * <カラãƒ?>値n</カラãƒ?> 041 * </ROW> 042 * ?¥?¥?¥ 043 * <ROW num="n"> 044 * ?¥?¥?¥ 045 * </ROW> 046 * <ROWSET> 047 * 048 * ã“ã?å½¢å¼ã§ã‚れã°ã€XDK(Oracle XML Developer's Kit)を利用ã™ã‚Œã°ã€?žå¸¸ã«ç°¡å˜ã« 049 * ãƒ??タベã?スã¨XMLファイルã¨ã®äº¤æ›ãŒå¯èƒ½ã§ã™ã? 050 * <a href="http://otn.oracle.co.jp/software/tech/xml/xdk/index.html" target="_blank" > 051 * XDK(Oracle XML Developer's Kit)</a> 052 * 053 * æ‹¡å¼µXDKå½¢å¼ã¨ã¯ã€ROW 以外ã«ã€SQL処ç?”¨ã‚¿ã‚°(EXEC_SQL)ã‚’æŒã¤ XML ファイルã§ã™ã? 054 * ã¾ãŸã?登録ã™ã‚‹ãƒ??ブル(table)ã‚?ROWSETã‚¿ã‚°ã®å±žæ?æƒ??ã¨ã—ã¦ä»˜ä¸Žã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã? 055 * (大æ–?—å°æ–‡å—ã«æ³¨æ„? 056 * ã“れã¯ã€ã‚ªãƒ©ã‚¯ãƒ«XDKã§å‡¦ç?™ã‚‹å?åˆã?無視ã•れã¾ã™ã?ã§ã€åŒæ§˜ã«æ‰±ã?“ã¨ãŒå?æ¥ã¾ã™ã? 057 * ã“ã?ã€EXEC_SQL ã¯ã€ãれãれã? XMLãƒ??タをデータベã?スã«ç™»éŒ²ã™ã‚‹éš›ã«ã€? 058 * SQL処ç?‚’è‡ªå‹•çš„ã«æµã™ç‚ºã®ã€SQLæ–?‚’記載ã—ã¾ã™ã? 059 * ã“ã?処ç??ã€ã‚¤ãƒ™ãƒ³ãƒˆæ¯Žã«å®Ÿè¡Œã•れる為ã€ãã®é…ç½®é ??é‡è¦ã§ã™ã? 060 * ã“ã?ã‚¿ã‚°ã¯ã€è¤?•°è¨˜è¿°ã™ã‚‹ã“ã¨ã‚‚å?æ¥ã¾ã™ãŒã€BODY部ã«ã¯ã€?¼‘ã¤ã®SQLæ–??ã¿è¨˜è¿°ã—ã¾ã™ã? 061 * 062 * <ROWSET tableName="XX" > 063 * <EXEC_SQL> æœ??ã«è¨˜è¼‰ã—ã¦ã€å?期å?ç?ãƒ??タクリアç?を実行ã•ã›ã‚‹ã€? 064 * delete from GEXX where YYYYY 065 * </EXEC_SQL> 066 * <MERGE_SQL> ã“ã?SQLæ–?§ UPDATEã—ã¦ã€çµæžœãŒï¼ä»¶ãªã‚‰INSERTを行ã„ã¾ã™ã? 067 * update GEXX set AA=[AA] , BB=[BB] where CC=[CC] 068 * </MERGE_SQL> 069 * <ROW num="1"> 070 * <カラãƒ?>値1</カラãƒ?> 071 * ?¥?¥?¥ 072 * <カラãƒ?>値n</カラãƒ?> 073 * </ROW> 074 * ?¥?¥?¥ 075 * <ROW num="n"> 076 * ?¥?¥?¥ 077 * </ROW> 078 * <EXEC_SQL> æœ?¾Œã«è¨˜è¼‰ã—ã¦ã€??ç›®ã®è¨å®?æ•´åˆæ?登録)を行ã†ã€? 079 * update GEXX set AA='XX' , BB='YY' where CC='ZZ' 080 * </EXEC_SQL> 081 * <ROWSET> 082 * 083 * DefaultHandler クラスを拡張ã—ã¦ã?‚‹ç‚ºã€??常ã®å‡¦ç?¨åŒæ§˜ã«ã€ä½¿ç”¨ã§ãã¾ã™ã? 084 * 085 * InputSource input = new InputSource( reader ); 086 * HybsXMLHandler hndler = new HybsXMLHandler(); 087 * 088 * SAXParserFactory f = SAXParserFactory.newInstance(); 089 * SAXParser parser = f.newSAXParser(); 090 * parser.parse( input,hndler ); 091 * 092 * ã¾ãŸã?上記ã?処ç?ã®ã‚‚ã?を簡略化ã—ãŸãƒ¡ã‚½ãƒ?ƒ‰:parse( Reader ) ã‚’æŒã£ã¦ã?‚‹ãŸã‚ã€? 093 * 通常ãã?メソãƒ?ƒ‰ã‚’使用ã—ã¾ã™ã? 094 * 095 * HybsXMLHandler ã«ã¯ã€TagElementListener ã‚’ã‚»ãƒ?ƒˆã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã? 096 * ã“れã¯ã€ROW 毎㫠å†?ƒ¨æƒ??ã‚?TagElement オブジェクト化ã—ã?action( TagElement ) 097 * ãŒå‘¼ã³å‡ºã•れã¾ã™ã?ã“ã? Listener を介ã—ã¦ã€?¼‘レコードãšã¤å‡¦ç?™ã‚‹ã“ã¨ã? 098 * å¯èƒ½ã§ã™ã? 099 * 100 * @version 4.0 101 * @author Kazuhiko Hasegawa 102 * @since JDK5.0, 103 */ 104 public class HybsXMLHandler extends DefaultHandler { 105 /** シスãƒ?ƒ ä¾å˜ã?改行記å·ã‚’ã‚»ãƒ?ƒˆã—ã¾ã™ã? */ 106 private static final String CR = System.getProperty("line.separator"); 107 108 /** ã“ã?ãƒãƒ³ãƒ‰ãƒ©ã®ãƒˆãƒƒãƒ—ã‚¿ã‚°å? {@value} */ 109 public static final String ROWSET = "ROWSET"; 110 /** ã“ã?ãƒãƒ³ãƒ‰ãƒ©ã§å–り扱ãˆã‚‹ ROWSETã‚¿ã‚°ã®å±žæ? */ 111 public static final String ROWSET_TABLE = "tableName"; 112 113 /** ã“ã?ãƒãƒ³ãƒ‰ãƒ©ã§å–り扱ãˆã‚‹ã‚¿ã‚°å? {@value} */ 114 public static final String ROW = "ROW"; 115 /** ã“ã?ãƒãƒ³ãƒ‰ãƒ©ã§å–り扱ãˆã‚‹ ROWã‚¿ã‚°ã®å±žæ? {@value} */ 116 public static final String ROW_NUM = "num"; 117 /** ã“ã?ãƒãƒ³ãƒ‰ãƒ©ã§å–り扱ãˆã‚‹ã‚¿ã‚°å? {@value} */ 118 public static final String EXEC_SQL = "EXEC_SQL"; 119 /** ã“ã?ãƒãƒ³ãƒ‰ãƒ©ã§å–り扱ãˆã‚‹ã‚¿ã‚°å? {@value} */ 120 public static final String MERGE_SQL = "MERGE_SQL"; 121 122 private Map<String,String> defaultMap = null; 123 private TagElementListener listener = null; 124 private TagElement element = null; 125 private String key = null; 126 private StringBuilder body = null; 127 private boolean bodyIn = false; 128 private int level = 0; 129 130 /** 131 * パã?ス処ç?‚’行ã„ã¾ã™ã? 132 * 通常ã®ãƒ‘ã?ス処ç??簡易メソãƒ?ƒ‰ã«ãªã£ã¦ã?¾ã™ã? 133 * 134 * @param reader パã?ス処ç?”¨ã®Readerオブジェクãƒ? 135 */ 136 public void parse( final Reader reader ) { 137 try { 138 SAXParserFactory fact = SAXParserFactory.newInstance(); 139 SAXParser parser = fact.newSAXParser(); 140 141 InputSource input = new InputSource( reader ); 142 143 try { 144 parser.parse( input,this ); 145 } 146 catch( SAXException ex ) { 147 if( ! "END".equals( ex.getMessage() ) ) { 148 String errMsg = "XMLパã?スエラー key=" + key + CR 149 + "element=" + element + CR 150 + ex.getMessage() ; 151 if( body != null ) { 152 errMsg = errMsg + CR + body.toString(); 153 } 154 throw new RuntimeException( errMsg,ex ); 155 } 156 } 157 } 158 catch( ParserConfigurationException ex1 ) { 159 String errMsg = "SAXParser ã®ã‚³ãƒ³ãƒ•ã‚£ã‚°ãƒ¬ãƒ¼ã‚·ãƒ§ãƒ³ãŒæ§‹ç¯‰ã§ãã¾ã›ã‚“ã€? 160 + "key=" + key + CR + ex1.getMessage(); 161 throw new RuntimeException( errMsg,ex1 ); 162 } 163 catch( SAXException ex2 ) { 164 String errMsg = "SAXParser ãŒæ§‹ç¯‰ã§ãã¾ã›ã‚“ã€? 165 + "key=" + key + CR + ex2.getMessage(); 166 throw new RuntimeException( errMsg,ex2 ); 167 } 168 catch( IOException ex3 ) { 169 String errMsg = "InputSource ã®èªã¿å–り時ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€? 170 + "key=" + key + CR + ex3.getMessage(); 171 throw new RuntimeException( errMsg,ex3 ); 172 } 173 } 174 175 /** 176 * å†?ƒ¨ã« TagElementListener を登録ã—ã¾ã™ã? 177 * ã“れã¯ã€?lt;ROW> ã‚¿ã‚°ã® endElement 処ç?¯Žã«å‘¼ã³å‡ºã•れã¾ã™ã? 178 * ã¤ã¾ã‚Šã?行データをå–å¾—é?度ã€TagElement オブジェクトを作æ?ã—ã? 179 * ã“ã? TagElementListener ã® action( TagElement ) メソãƒ?ƒ‰ã‚’呼ã³å‡ºã—ã¾ã™ã? 180 * 何もセãƒ?ƒˆã—ãªã??ã¾ãŸã?ã€null ãŒã‚»ãƒ?ƒˆã•れãŸå?åˆã?ã€ä½•ã‚‚ã—ã¾ã›ã‚“ã€? 181 * 182 * @param listener TagElementListenerオブジェクãƒ? 183 */ 184 public void setTagElementListener( final TagElementListener listener ) { 185 this.listener = listener; 186 } 187 188 /** 189 * TagElement オブジェクトを作æ?ã™ã‚‹æ™‚ã? åˆæœŸã‚«ãƒ©ãƒ?値をè¨å®šã—ã¾ã™ã? 190 * TagElements オブジェクトã?ã€XMLファイルより作æ?ã™ã‚‹ç‚ºã€??ç›®(カラãƒ?ã‚? 191 * XMLファイルã®ROW属æ?ã«æŒã£ã¦ã?‚‹é ?›®ã¨å€¤ã§ä½œæ?ã•れã¾ã™ã? 192 * ã“ã?カラãƒ?ã‚’ã?外部ã‹ã‚‰åˆæœŸè¨å®šã™ã‚‹ã“ã¨ãŒå¯èƒ½ã§ã™ã? 193 * ãã?å ´åˆã?ã“ã“ã§ç™»éŒ²ã—ãŸã‚«ãƒ©ãƒ??(Mapã«ã€LinkedHashMap を使用ã—ãŸå ´å? 194 * ãŒä¿æŒã•れã¾ã™ã?ã¾ãŸã?ROW属æ?ã«å˜åœ¨ã—ãªã?‚«ãƒ©ãƒ?Œã‚れã°ã€å?ã¨ã¨ã‚‚ã« 195 * åˆæœŸå€¤ã¨ã—ã¦è¨å®šã—ã¦ãŠãã“ã¨ãŒå¯èƒ½ã§ã™ã? 196 * ãªãŠã?ã“ã“ã§ã®Mapã¯ã€ç›´æŽ¥è¨å®šã—ã¦ã?¾ã™ã?ã§ã€ã”注æ„ãã?•ã?? 197 * 198 * @param map åˆæœŸã‚«ãƒ©ãƒ??ãƒ?? 199 */ 200 public void setDefaultMap( final Map<String,String> map ) { 201 defaultMap = map; 202 } 203 204 /** 205 * è¦ç´??ã®æ–?—データã®é€šçŸ¥ã‚’å—ã‘å–りã¾ã™ã? 206 * インタフェース ContentHandler å†?? characters メソãƒ?ƒ‰ã‚’オーãƒã?ライドã—ã¦ã?¾ã™ã? 207 * å?–‡å—データãƒãƒ£ãƒ³ã‚¯ã«å¯¾ã—ã¦ç‰¹æ®Šãªã‚¢ã‚¯ã‚·ãƒ§ãƒ³ (ノã?ドã¾ãŸã?ãƒãƒƒãƒ•ã‚¡ã¸ã®ãƒ??ã‚¿ã®è¿½åŠ?? 208 * ãƒ??ã‚¿ã®ãƒ•ァイルã¸ã®å‡ºåŠ›ãªã©) を実行ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã? 209 * 210 * @param buffer æ–?—データé…å? 211 * @param start é…å?å†??é–‹å§‹ä½ç½® 212 * @param length é…å?ã‹ã‚‰èªã¿å–られるæ–?—æ•° 213 * @see org.xml.sax.helpers.DefaultHandler#characters(char[] , int , int ) 214 */ 215 @Override 216 public void characters( final char[] buffer, final int start, final int length ) throws SAXException { 217 if( ! ROW.equals( key ) && ! ROWSET.equals( key ) && length > 0 ) { 218 body.append( buffer,start,length ); 219 bodyIn = true; 220 } 221 } 222 223 /** 224 * è¦ç´??é–‹å§‹é?知をå—ã‘å–りã¾ã™ã? 225 * インタフェース ContentHandler å†?? startElement メソãƒ?ƒ‰ã‚’オーãƒã?ライドã—ã¦ã?¾ã™ã? 226 * パã?サ㯠XML æ–?›¸å†??å?¦ç´??å‰ã§ã“ã?メソãƒ?ƒ‰ã‚’呼ã³å‡ºã—ã¾ã™ã? 227 * å?startElement イベントã«ã¯å¯¾å¿œã™ã‚?endElement イベントãŒã‚りã¾ã™ã? 228 * ã“れã¯ã€è¦ç´?Œç©ºã§ã‚ã‚‹å ´åˆã‚‚変ã‚りã¾ã›ã‚“。対応ã™ã‚?endElement イベントã?å‰ã«ã€? 229 * è¦ç´??コンãƒ?ƒ³ãƒ??部ãŒé?番ã«å ±å‘Šã•れã¾ã™ã? 230 * ã“ã“ã§ã¯ã€ã‚¿ã‚°ãŒãƒ¬ãƒ™ãƒ«?“以上ã?å ´åˆã?ã€ä¸Šä½ã‚¿ã‚°ã®å†?®¹ã¨ã—ã¦å–り扱ã?¾ã™ã?よã£ã¦ã€? 231 * ã‚¿ã‚°ã«åå‰ç©ºé–“ãŒå®šç¾©ã•れã¦ã?‚‹å ´åˆã?ãã?属æ?ã¯å‰Šé™¤ã—ã¾ã™ã? 232 * 233 * @param namespace åå‰ç©ºé–??µ?²?© 234 * @param localName å‰ç½®ä¿®é£¾åã‚’å«ã¾ãªã?ƒãƒ¼ã‚«ãƒ«åã?åå‰ç©ºé–“å?ç?Œè¡Œã‚れãªã??åˆã?空æ–?—å? 235 * @param qname å‰ç½®ä¿®é£¾åã‚’æŒã¤ä¿®é£¾åã?修飾åを使用ã§ããªã??åˆã?空æ–?—å? 236 * @param attributes è¦ç´?«ä»˜åŠ ã•れãŸå±žæ?。属æ?ãŒå˜åœ¨ã—ãªã??åˆã?空㮠Attributesオブジェクãƒ? 237 * @see org.xml.sax.helpers.DefaultHandler#startElement(String , String , String , Attributes ) 238 */ 239 @Override 240 public void startElement(final String namespace, final String localName, 241 final String qname, final Attributes attributes) throws SAXException { 242 if( ROWSET.equals( qname ) ) { 243 if( listener != null ) { 244 element = new TagElement( ROWSET,defaultMap ); 245 element.put( ROWSET_TABLE,attributes.getValue( ROWSET_TABLE ) ); 246 listener.actionInit( element ); 247 } 248 element = null; 249 } 250 else if( ROW.equals( qname ) ) { 251 element = new TagElement( ROW,defaultMap ); 252 String num = attributes.getValue( ROW_NUM ); 253 element.setRowNo( num ); 254 } 255 else if( EXEC_SQL.equals( qname ) ) { 256 element = new TagElement( EXEC_SQL ); 257 } 258 else if( MERGE_SQL.equals( qname ) ) { 259 element = new TagElement( MERGE_SQL ); 260 } 261 262 if( level <= 2 ) { 263 key = qname; 264 body = new StringBuilder(); 265 } 266 else { 267 // レベル??以上ã?ã‚¿ã‚°ã¯ä¸Šä½ã‚¿ã‚°ã®å†?®¹ã¨ã—ã¦æ‰±ã?¾ã™ã? 268 body.append( "<" ).append( qname ); 269 int len = attributes.getLength(); 270 for( int i=0; i<len; i++ ) { 271 // åå‰ç©ºé–“ã?宣è¨??ã€å‰Šé™¤ã—ã¦ãŠãã¾ã™ã?ã‚ãã¾ã§ãƒ??ã‚¿ã¨ã—ã¦å–り扱ã?‚ºã§ã™ã? 272 String attr = attributes.getQName(i); 273 if( ! attr.startsWith( "xmlns:" ) ) { 274 body.append( " " ); 275 body.append( attr ).append( "=\"" ); 276 body.append( attributes.getValue(i) ).append( "\"" ); 277 } 278 } 279 body.append( ">" ); 280 } 281 282 bodyIn = false; // 入れå状ã®ã‚¿ã‚°ã®BODYéƒ¨ã®æœ‰ç„¡ 283 level ++ ; 284 } 285 286 /** 287 * è¦ç´??終äº??知をå—ã‘å–りã¾ã™ã? 288 * インタフェース ContentHandler å†?? endElement メソãƒ?ƒ‰ã‚’オーãƒã?ライドã—ã¦ã?¾ã™ã? 289 * SAX パã?サã¯ã€XML æ–?›¸å†??å?¦ç´??終ã‚りã«ã“ã?メソãƒ?ƒ‰ã‚’呼ã³å‡ºã—ã¾ã™ã? 290 * å?endElement イベントã«ã¯å¯¾å¿œã™ã‚?startElement イベントãŒã‚りã¾ã™ã? 291 * ã“れã¯ã€è¦ç´?Œç©ºã§ã‚ã‚‹å ´åˆã‚‚変ã‚りã¾ã›ã‚“ã€? 292 * 293 * @param namespace åå‰ç©ºé–?URI 294 * @param localName å‰ç½®ä¿®é£¾åã‚’å«ã¾ãªã?ƒãƒ¼ã‚«ãƒ«åã?åå‰ç©ºé–“å?ç?Œè¡Œã‚れãªã??åˆã?空æ–?—å? 295 * @param qname å‰ç½®ä¿®é£¾åã‚’æŒã¤ XML 1.0 修飾åã?修飾åを使用ã§ããªã??åˆã?空æ–?—å? 296 * @see org.xml.sax.helpers.DefaultHandler#endElement(String , String , String ) 297 */ 298 @Override 299 public void endElement(final String namespace, final String localName, final String qname) throws SAXException { 300 level -- ; 301 if( ROW.equals( qname ) ) { 302 if( listener != null ) { 303 listener.actionRow( element ); 304 } 305 element = null; 306 } 307 else if( EXEC_SQL.equals( qname ) ) { 308 element.setBody( body.toString().trim() ); 309 if( listener != null ) { 310 listener.actionExecSQL( element ); 311 } 312 element = null; 313 } 314 else if( MERGE_SQL.equals( qname ) ) { 315 element.setBody( body.toString().trim() ); 316 if( listener != null ) { 317 listener.actionMergeSQL( element ); 318 } 319 element = null; 320 } 321 else if( level <= 2 ) { 322 if( element != null ) { 323 element.put( key , body.toString().trim() ); 324 } 325 } 326 else { 327 if( bodyIn ) { 328 body.append( "</" ).append( qname ).append( ">" ); 329 } 330 else { 331 body.insert( body.length()-1, " /" ); // ã‚¿ã‚°ã®æœ?¾Œã‚’ " />" ã¨ã™ã‚‹ã€? 332 } 333 } 334 } 335 }