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 */ 016package org.opengion.plugin.develop; 017 018import java.util.ArrayList; 019import java.util.List; 020import java.util.Map; 021import java.util.HashMap; 022import java.util.regex.Matcher; 023import java.util.regex.Pattern; 024 025import org.opengion.hayabusa.develop.AbstractJspCreate; 026import org.opengion.hayabusa.develop.JspEnumeration.GROUPING_FUNCTIONS ; 027import org.opengion.hayabusa.develop.JspEnumeration.WHERE_OPERATORS ; 028import org.opengion.hayabusa.develop.JspConvertEntity; 029import org.opengion.fukurou.xml.OGElement; 030import static org.opengion.fukurou.util.StringUtil.isNull; 031 032/** 033 * result.jspの<og:query >タグを作成します。 034 * 035 * ●使用例 036 * <og:query 037 * command = "{@command}" 038 * debug = "{@debug} 039 * dbid = "{@FROM_DBID}" 040 * maxRowCount = "{@maxRowCount}" > 041 * select A1.xx , A1.xx ,・・・ 042 * from xxx A1 inner join xxx B1 043 * where ・・・ 044 * group by ・・・ 045 * having ・・・ 046 * ORDER BY ・・・ 047 * </og:query> 048 * 049 * @og.rev 5.6.1.2 (2013/02/22) 文字列連結から、XML処理するように変更します。 050 * @author Takeshi.Takada 051 * 052 */ 053public class JspCreate_QUERY extends AbstractJspCreate { 054 //* このプログラムのVERSION文字列を設定します。 {@value} */ 055 private static final String VERSION = "5.6.4.4 (2013/05/31)" ; 056 057 private List<JspConvertEntity> QUERY_ROWS ; 058 private List<JspConvertEntity> RESULT_ROWS ; 059 private List<JspConvertEntity> CONST_ROWS ; 060 private List<JspConvertEntity> JOIN_ROWS ; 061 private List<JspConvertEntity> JOIN_ON_ROWS ; 062 private List<JspConvertEntity> HAVING_ROWS ; 063 064 private String ns = ""; // 5.2.1.0 (2010/10/01) 名前空間 065 066 /** 067 * 初期化メソッド 068 * 069 * 内部で使用する JspConvertEntity の リスト のマップを受け取り、初期化を行います。 070 * 071 * @og.rev 5.2.1.0 (2010/10/01) 名前空間を、og 決め打ちから、名前空間指定無しに変更します。 072 * 073 * @param master JspConvertEntityのリストのマップ 074 */ 075 @Override 076 protected void init( final Map<String,List<JspConvertEntity>> master ) { 077 QUERY_ROWS = master.get( "QUERY" ); 078 RESULT_ROWS = master.get( "RESULT" ); 079 CONST_ROWS = master.get( "CONST" ); 080 JOIN_ROWS = master.get( "JOIN" ); 081 JOIN_ON_ROWS= master.get( "JOIN_ON" ); 082 HAVING_ROWS = master.get( "HAVING" ); 083 084// KEY = "og:query"; 085 KEY = ":query"; // 5.2.1.0 (2010/10/01) 名前空間指定無し 086 NAME = "result"; 087 } 088 089 /** 090 * JSPに出力するタグの内容を作成します。 091 * 引数より作成前のタグの属性内容を確認するする事が出来ます。 092 * 093 * @og.rev 5.2.1.0 (2010/10/01) メソッドの引数を、OGAttributes から OGElement に変更します。 094 * @og.rev 5.2.1.0 (2010/10/01) 名前空間を、og 決め打ちから、引数を使用するように変更します。 095 * @og.rev 5.6.4.4 (2013/05/31) select カラムに、コメントを付与します。 096 * 097 * @param ele OGElementエレメントオブジェクト 098 * @param nameSpace このドキュメントのnameSpace( og とか mis とか ) 099 * 100 * @return 変換された文字列 101 * @throws Throwable 変換時のエラー 102 */ 103 @Override 104 protected String execute( final OGElement ele , final String nameSpace ) throws Throwable { 105 ns = (nameSpace.length() == 0) ? "" : nameSpace + ":" ; // 5.2.1.0 (2010/10/01) 名前空間 106 107 // この OGElement の階層の深さを探ります。 108 // ele.getText( para ) とすることでXML全体を階層表示できる。 109 // int para = ele.getParentCount(); 110 111 // TODO Auto-generated method stub 112 //書き出す文字列を作成開始。 113 StringBuilder tag = new StringBuilder(); 114 115 List<String> selects = new ArrayList<String>(); 116 List<String> clmCmnt = new ArrayList<String>(); // 5.6.4.4 (2013/05/31) select カラムに、コメントを付与します。 117 List<String> tables = new ArrayList<String>(); 118 List<String> orders = new ArrayList<String>(); 119 List<String> group = new ArrayList<String>(); 120 List<String> having_part = new ArrayList<String>(); 121 List<String> having_grouping_column = new ArrayList<String>(); 122 123 //HAVING情報から<og:query>タグのテキスト部を生成する準備をします。 124// if ( HAVING_ROWS != null && HAVING_ROWS.size() > 0 ){ 125 if ( isNotEmpty(HAVING_ROWS) ){ 126 for( JspConvertEntity row : HAVING_ROWS ){ 127 having_part.add(row.getRemarks()); 128 if( GROUPING_FUNCTIONS.search( row.getRemarks() ) ){ 129 having_grouping_column.add( row.getFullColumnName() ); 130 } 131 } 132 } 133 //RESULT情報から<og:query>タグのテキスト部を生成する準備をします。 134 boolean grouping = false; 135// if( RESULT_ROWS != null ) { 136 if ( isNotEmpty(RESULT_ROWS) ){ 137 for(int i = 0 ; i < RESULT_ROWS.size() ; i++){ 138 JspConvertEntity result = RESULT_ROWS.get(i); 139 //Select句の情報を作成 140 selects.add( result.getSelectPartColumnName() ); 141 // 5.6.4.4 (2013/05/31) select カラムに、コメントを付与します。 142 clmCmnt.add( result.getTableName() + "." + result.getColumnCommentName() ); 143 //テーブル名を検証して、テーブル数のみの情報にします。 144 if( tables != null && !tables.contains( result.getTableName() ) ) { 145 tables.add( result.getFromPartTableName() ); 146 } 147 //並び順に利用するカラムを取得する。 148 if ("1".equals( result.getUseOrder() )) { 149 orders.add(Integer.toString( i + 1 )); 150 } 151 //GROUP BYに必要な情報を取得します。 152 if( GROUPING_FUNCTIONS.contains( result.getRemarks() ) ){ 153 grouping = true; 154 // }else if(having_grouping_column.indexOf( result.getFullColumnName() ) > -1 ){ 155 // group.add( result.getFullColumnName() ); 156 }else{ 157 group.add( result.getFullColumnName() ); 158 } 159 } 160 } 161 162 //JOIN情報から<og:query>タグのテキスト部(join句)を生成する準備をします。 163 JspConvertEntity join_on = null; 164// if (JOIN_ON_ROWS != null && JOIN_ON_ROWS.size() > 0 ) { 165 if ( isNotEmpty(JOIN_ON_ROWS) ){ 166 join_on = JOIN_ON_ROWS.get( 0 ); 167 } 168 //JOIN情報から<og:query><og:where><og:and>タグの検索句を生成する準備をします。 169// if( QUERY_ROWS != null && CONST_ROWS != null && CONST_ROWS.size() > 0 ) { 170 if ( QUERY_ROWS != null && isNotEmpty(CONST_ROWS) ){ 171 QUERY_ROWS.addAll( CONST_ROWS ); 172 } 173 174// tag.append("<og:query command=\"{@command}\" debug=\"{@debug}\" dbid=\"{@FROM_DBID}\" maxRowCount=\"{@maxRowCount}\">").append( CR ); 175// tag.append("<" ).append( ns ).append( "query command=\"{@command}\" debug=\"{@debug}\" dbid=\"{@FROM_DBID}\" maxRowCount=\"{@maxRowCount}\">").append( CR ); 176 177 OGElement queryEle = new OGElement( ns + "query" ); 178 queryEle.addAttr( "command" ,"{@command}" ); 179 queryEle.addAttr( "debug" ,"{@debug}" ); 180 queryEle.addAttr( "dbid" ,"{@FROM_DBID}" ); 181 queryEle.addAttr( "maxRowCount" ,"{@maxRowCount}" ); 182 183// tag.append( queryText(selects , tables , JOIN_ROWS , join_on ) ); 184 185// queryEle.addNode( queryText(selects , tables , JOIN_ROWS , join_on ) ); 186 queryEle.addNode( queryText(selects , clmCmnt , tables , JOIN_ROWS , join_on ) ); // 5.6.4.4 (2013/05/31) select カラムに、コメントを付与 187 188// tag.append( CR ); 189// if ( QUERY_ROWS != null && QUERY_ROWS.size() > 0 ){ 190 if ( isNotEmpty(QUERY_ROWS) ){ 191// tag.append("\t<og:where>").append( CR ); 192// tag.append("\t<").append( ns ).append("where>").append( CR ); 193 194 OGElement whereEle = new OGElement( ns + "where" ); 195 196 for ( JspConvertEntity where : QUERY_ROWS ) { 197 if ("QUERY".equals(where.getType())){ 198// tag.append(andWhereQuery(where.getFullColumnName() , where.getRemarks() ,"{@"+ where.getColumnName() +"}" ,where.isNumber())); 199 whereEle.addNode( andWhereQuery(where.getFullColumnName() , where.getRemarks() ,"{@"+ where.getColumnName() +"}" ,where.isNumber()) ); 200 } 201 if ("CONST".equals(where.getType())) { 202// tag.append(andWhereConst( where.getFullColumnName(), where.getRemarks() , where.isNumber())); 203 whereEle.addNode( andWhereConst( where.getFullColumnName(), where.getRemarks() , where.isNumber()) ); 204 } 205 } 206// tag.append("\t</og:where>").append( CR ); 207// tag.append("\t</").append( ns ).append( "where>").append( CR ); 208 queryEle.addNode( whereEle ); 209 } 210// if ( grouping == true || having_grouping_column.size() > 0 ) { 211// if ( grouping || having_grouping_column.size() > 0 ) { 212 if ( grouping || !having_grouping_column.isEmpty() ) { 213// tag.append( "\t\tgroup by " ).append(chainChar(group,",")).append( CR ); 214// queryEle.addNode( "\t\tgroup by " + chainChar(group,",") + CR ); 215 queryEle.addNode( T2 + "group by " + chainChar(group,",") + CR ); 216 } 217// if ( having_grouping_column.size() > 0 ){ 218 if ( !having_grouping_column.isEmpty() ){ 219// tag.append( "\t\thaving " ).append(chainChar(having_part ," and ")).append( CR ); 220// queryEle.addNode( "\t\thaving " + chainChar(having_part ," and ") + CR ); 221 queryEle.addNode( T2 + "having " + chainChar(having_part ," and ") + CR ); 222 } 223// if ( orders.size() > 0 ){ 224 if ( !orders.isEmpty() ){ 225// tag.append( apperText("ORDER BY" , "ORDER_BY" , orders ) ); 226 queryEle.addNode( apperEle( "ORDER BY" , "ORDER_BY" , orders ) ); 227 } 228// tag.append( CR ); 229// tag.append("</og:query>").append( CR ); 230// tag.append("</").append( ns ).append( "query>").append( CR ); 231 232// return tag.toString(); 233 return queryEle.getText(0); 234 } 235 236 private static final String SPACE = " " ; // カラムの位置合わせ用 237 238 /** 239 * result.jspのog:queryタグのテキスト部を生成します。 240 * 241 * 補足1 242 * 引数のjoin_onがnullでないときは、優先的にjoin_onの内容でJOIN句を生成します。 243 * 244 * @og.rev 5.6.4.4 (2013/05/31) select カラムに、コメントを付与します。 245 * 246 * @param selects 検索SQLのリスト 247 * @param clmCmnt カラムコメントのリスト 248 * @param tables テーブル名のリスト 249 * @param joins JspConvertEntityのリスト 250 * @param join_on JspConvertEntityオブジェクト 251 * 252 * @return og:queryタグのテキスト部 253 */ 254// protected String queryText( final List<String> selects , final List<String> tables , 255// final List<JspConvertEntity> joins ,final JspConvertEntity join_on ) { 256 protected String queryText( final List<String> selects , final List<String> clmCmnt , final List<String> tables , 257 final List<JspConvertEntity> joins ,final JspConvertEntity join_on ) { 258 StringBuilder sb = new StringBuilder(); 259// sb.append( CR ).append( "\t\tselect" ).append( CR ); 260 sb.append( CR ).append( T2 ).append( "select" ).append( CR ); 261// sb.append( "\t\t\t" ); 262// sb.append( T3 ); 263// sb.append( chainChar( selects , "," ) ); // 5.6.4.4 (2013/05/31) 以前は、カラムをカンマで単純につなげていただけ。 264 // 5.6.4.4 (2013/05/31) select カラムに、コメントを付与します。 265 int size = selects.size(); 266 for( int i=0; i<size; i++ ) { 267 sb.append( T3 ); 268 if( i == 0 ) { sb.append( " " ); } 269 else { sb.append( "," ); } 270 String clm = selects.get(i) ; 271 sb.append( clm ).append( SPACE.substring( clm.length() ) ).append( T3 ).append( T3 ).append( T3 ).append( T3 ); 272 sb.append( "<!-- " ).append( clmCmnt.get(i) ).append( " -->" ).append( CR ); 273 } 274 275// sb.append( CR ); 276// sb.append( "\t\tfrom " ); 277 sb.append( T2 ).append( "from " ); 278 279 if ( join_on != null ) { 280 //JOIN_ONが存在する場合は、直接SQLを組み立てて処理を終了する。 281// sb.append( "\t\t" ); 282 sb.append( T2 ); 283 sb.append( join_on.getRemarks() ); 284 return sb.toString(); 285 } 286 287// if( joins == null || joins.isEmpty() ) { 288 if( !isNotEmpty( joins ) ) { 289 sb.append( tables.get(0) ); 290 return sb.toString(); 291 } 292 293 //テーブルの内容を構造化します。 294 TableStruct structs = createStruct(joins); 295 296 String before_left = ""; 297 String before_right = ""; 298 StringBuilder sbPre = new StringBuilder(""); 299 300 Map<String,String> mapJoinParts = new HashMap<String,String>(); 301 302 boolean isStartJoin = false; 303 304 for(int i = 0 ; i < joins.size() ; i++){ 305 //join句を作るのとネスト構造を作るのは処理を分離させる。 306 JspConvertEntity join = joins.get( i ); 307 308 if(before_left.equals(join.getFromPartTableName())){ 309 //前の処理と左側のテーブルは同じ 310// if( before_right.equals(join.getJoinColumn().getFromPartTableName()) == false ) { 311 if( ! before_right.equals(join.getJoinColumn().getFromPartTableName()) ) { 312 //前の処理と右側のテーブルが違う 313 sbPre.append( sqlJoinOn( "", join.getJoinColumn().getFromPartTableName() , join.getJoinType()) ); 314 isStartJoin = true; 315 } 316 }else { 317 //前の処理と左側のテーブルが違う 318// if( before_right.equals(join.getJoinColumn().getFromPartTableName()) == false ) { 319 if( ! before_right.equals(join.getJoinColumn().getFromPartTableName()) ) { 320 //前の処理と右側のテーブルが違う 321 //前の処理のJoin句をテーブル名別にセット 322 String str = sbPre.toString(); 323 mapJoinParts.put( before_left, str ); 324 //バッファを初期化 325 sbPre = new StringBuilder(); 326 sbPre.append( sqlJoinOn( join.getFromPartTableName() , join.getJoinColumn().getFromPartTableName() , join.getJoinType()) ); 327 isStartJoin = true; 328 } 329 } 330// if ( isStartJoin == false ) { 331 if ( !isStartJoin ) { 332// sbPre.append( " and").append( CR ); 333// sbPre.append( CR ).append( "\t\t\tand\t"); 334 sbPre.append( CR ).append( T3 ).append( "and").append( T1 ); 335 } 336// sbPre.append( "\t\t\t" ); 337 sbPre.append( join.getFullColumnName() ); 338// sbPre.append( "\t\t=\t" ); 339 sbPre.append( T2 ).append( "=" ).append( T1 ); 340 sbPre.append( join.getJoinColumn().getFullColumnName() ); 341 before_left = join.getFromPartTableName(); 342 before_right = join.getJoinColumn().getFromPartTableName(); 343 isStartJoin = false; 344 } 345 //最終分 346 mapJoinParts.put( before_left, sbPre.toString() ); 347 348 StringBuilder sbJoin = new StringBuilder(); 349 //Join句を組み立てます。 350// sb.append( createJoinPart(structs.getJoinTables(),mapJoinParts,sbJoin).toString() ); 351 createJoinPart(structs.getJoinTables(),mapJoinParts,sbJoin); 352 sb.append( sbJoin.toString() ); 353 354 return sb.toString(); 355 } 356 357 /** 358 * join句の一部を作成する。 359 * 360 * @param left join句のレフト 361 * @param right join句のライト 362 * @param join_type [1:inner join/その他:left outer join] 363 * 364 * @return join句の一部 365 */ 366 private String sqlJoinOn(final String left , final String right ,final String join_type){ 367 StringBuilder sb = new StringBuilder(); 368// sb.append( " " ).append( CR ); 369 sb.append( " " ); 370 sb.append( left ); 371 if("1".equals( join_type )){ 372 sb.append( " inner join " ); 373 }else{ 374 sb.append( " left outer join " ); 375 } 376 sb.append( right ); 377// sb.append( " on" ).append( CR ); 378// sb.append( CR ).append( "\t\t\ton\t" ); 379 sb.append( CR ).append( T3 ).append( "on" ).append( T1 ); 380 return sb.toString(); 381 } 382 383 /** 384 * JOIN句を組み立てます。 385 * 386 * JOIN句は、内部で再帰処理されます。引数の StringBuilder に最終的な JOIN句が格納されます。 387 * 388 * @param structs テーブル内容の構造化TableStructのリスト 389 * @param join JOIN句マップ 390 * @param buff StringBuilderオブジェクト 391 */ 392 private void createJoinPart( final List<TableStruct> structs , final Map<String,String> join ,final StringBuilder buff ) { 393 Matcher matcher = null; 394 for(int i = 0 ; i < structs.size() ; i++){ 395 TableStruct struct = structs.get(i); 396 String part = join.get(struct.getTableName()); 397 if ( part != null ){ 398// matcher = Pattern.compile( "join " + struct.getTableName() + " on").matcher( buff ); 399 matcher = Pattern.compile( "join " + struct.getTableName() ).matcher( buff ); 400 if( matcher.find()) { 401 int start = matcher.start(); 402 buff.delete(start,matcher.end()); 403// buff.insert(start , "join ( " + part + " ) on"); 404 buff.insert(start , "join ( " + part + " )" ); 405 }else{ 406 buff.append( part ); 407 } 408 } 409 createJoinPart(struct.getJoinTables(),join,buff); 410 } 411 } 412 413 /** 414 * result.jspの og:query og:appear タグを生成します。 415 * 416 * @og.rev 5.2.1.0 (2010/10/01) 名前空間を、og 決め打ちから、引数を使用するように変更します。 417 * 418 * @param start_key 開始キー 419 * @param value 値 420 * @param default_value 初期値リスト 421 * 422 * @return og:query og:appear タグ 423 */ 424// protected String apperText( final String start_key , final String value , final List<String> default_value ){ 425 protected OGElement apperEle( final String start_key , final String value , final List<String> default_value ){ 426// StringBuilder sb = new StringBuilder(); 427// sb.append( "\t<").append( ns ).append( "appear startKey = \"" ); 428// sb.append( start_key ); 429// sb.append( "\" value = \"{@" ); 430// sb.append( value ); 431// sb.append( "}\"" ).append( CR ); 432// sb.append( "\t\t\tdefaultVal = \"" ); 433// sb.append( chainChar( default_value , "," ) ); 434// sb.append( "\" />" ).append( CR ); 435// return sb.toString(); 436 437 OGElement apper = new OGElement( ns + "appear" ); 438 apper.addAttr( "startKey" ,start_key ); 439 apper.addAttr( "value" ,"{@" + value + "}" ); 440 apper.addAttr( "defaultVal" ,chainChar( default_value , "," ) ); 441 return apper; 442 } 443 444 /** 445 * result.jspの og:query og:where og:and タグを生成します。 446 * 処理グループ:QUERY 447 * 448 * @param left 左側式 449 * @param operator オペレーター 450 * @param right 右側式 451 * @param is_number 数字かどうか[true/false] 452 * 453 * @return og:and タグ 454 */ 455// protected String andWhereQuery( final String left , final String operator , final String right , final boolean is_number){ 456 protected OGElement andWhereQuery( final String left , final String operator , final String right , final boolean is_number){ 457// StringBuilder sb = new StringBuilder(); 458// if ( operator == null || operator.trim().length() == 0 ){ 459// if ( operator == null || operator.trim().isEmpty() ){ 460// operator = "eq"; 461// } 462 463 String ope = isNull(operator) ? "eq" : operator ; 464 465 WHERE_OPERATORS wrOpe = WHERE_OPERATORS.valueOf( ope ); 466// sb.append( "\t\t<og:and value = \"" ).append( wrOpe.apply( left , right , is_number )).append( "\"\t/>" ).append( CR ); 467// sb.append( "\t\t<").append( ns ).append( "and value = \"" ).append( wrOpe.apply( left , right , is_number )).append( "\"\t/>" ).append( CR ); 468// return sb.toString(); 469 470 OGElement and = new OGElement( ns + "and" ); 471 and.addAttr( "value" , wrOpe.apply( left , right , is_number ) ); 472 return and; 473 } 474 475 /** 476 * result.jspのog:query og:where og:and タグを生成します。 477 * 処理グループ:CONST 478 * 479 * @param left 左側式 480 * @param right 右側式 481 * @param is_number 数字かどうか[true/false] 482 * 483 * @return og:and タグ 484 */ 485// protected String andWhereConst( final String left , final String right , final boolean is_number ){ 486 protected OGElement andWhereConst( final String left , final String right , final boolean is_number ){ 487// String operator = ""; 488// if ( right.indexOf( "," ) >= 0 ) { 489// operator = "in"; 490// }else{ 491// operator = "eq"; 492// } 493 String operator = ( right.indexOf( ',' ) >= 0 ) ? "in" : "eq"; 494 return andWhereQuery( left , operator , right , is_number ); 495 } 496 497 /** 498 * query.jspの og:column タグを生成します。 499 * 500 * @param name タグのname 501 * @param default_value 初期値 502 * 503 * @return og:columnタグ 504 */ 505// protected String columnText( final String name , final String default_value ){ 506// StringBuilder sb = new StringBuilder(); 507// // sb.append( "\t<og:column name=\"" ); 508// sb.append( "\t<").append( ns ).append( "column name=\"" ); 509// sb.append( name ); 510// sb.append( "\"" ); 511// if ( default_value != null ) { 512// sb.append( " defaultVal=\"" ); 513// sb.append( default_value ); 514// sb.append( "\" " ); 515// } 516// sb.append("/>"); 517// return sb.toString(); 518// } 519 520 /** 521 * テーブルの結合関係を再現する構造体につめ直すメソッド 522 * 523 * @param joins JspConvertEntityのリスト 524 * 525 * @return テーブルの結合関係を再現する構造体 526 */ 527 private TableStruct createStruct( final List<JspConvertEntity> joins ) { 528 TableStruct st = new TableStruct(); 529 for(int i = 0 ; i < joins.size() ; i++){ 530 JspConvertEntity join = joins.get( i ); 531 String left_name = join.getFromPartTableName(); 532 String right_name = join.getJoinColumn().getFromPartTableName(); 533 534 TableStruct left = st.getJoinTable( left_name ); 535 TableStruct right = st.getJoinTable( right_name ); 536 537 if (left == null && right == null) { 538 //全くの新規。 539 left = new TableStruct(); 540 left.setTableName( left_name ); 541 right = new TableStruct(); 542 right.setTableName(right_name); 543 left.addJoinTable( right ); 544 st.addJoinTable( left ); 545 }else{ 546 if( left != null && right == null ){ 547 right = new TableStruct(); 548 right.setTableName(right_name); 549 left.addJoinTable( right ); 550 } 551 } 552 } 553 return st; 554 } 555 556 /** 557 * テーブルの結合状態を階層構図にする為のオブジェクト 558 * 559 * @author Administrator 560 * 561 */ 562 private static class TableStruct { 563 564 private final List<TableStruct> _joins = new ArrayList<TableStruct>(); 565 private String _table_name; 566 567 /** 568 * テーブル名を設定 569 * 570 * @param table_name String 571 */ 572 public void setTableName( final String table_name ) { 573 _table_name = table_name; 574 } 575 576 /** 577 * テーブル名を取得 578 * 579 * @return テーブル名 580 */ 581 public String getTableName() { 582 return _table_name; 583 } 584 585 /** 586 * 結合テーブルを追加 587 * 588 * @param join_table String 589 */ 590 public void addJoinTable( final TableStruct join_table ) { 591 _joins.add(join_table); 592 } 593 594 /** 595 * 結合テーブルを全て取得 596 * 597 * @return 全ての結合テーブル 598 */ 599 public List<TableStruct> getJoinTables() { 600 return _joins; 601 } 602 603 /** 604 * 指定したテーブルを取得 605 * 606 * @param table_name String 607 * @return 指定したテーブル 608 */ 609 public TableStruct getJoinTable( final String table_name ) { 610 return search(_joins,table_name); 611 } 612 613 /** 614 * テーブル同士が一致しているか検証する。 615 * 616 * @param table_name String 617 * @return 検証した結果の真偽 618 */ 619 public boolean equalTable( final String table_name ) { 620 return (_table_name != null && _table_name.equals( table_name )) ; 621// if(_table_name != null && _table_name.equals( table_name )) { 622// return true; 623// }else{ 624// return false; 625// } 626 } 627 628 /** 629 * 指定したテーブルが存在しているか検証する。 630 * 631 * @param table_name String 632 * @return 検証した結果の真偽 633 */ 634 public boolean constains( final String table_name ) { 635 for(int i = 0; i < _joins.size() ; i++){ 636 TableStruct join = _joins.get( i ); 637// if(join.equals(table_name)){ 638 if(join.equalTable(table_name)){ 639 return true; 640 } 641 } 642 return false; 643 } 644 645 /** 646 * 結合先を含めて指定したテーブルを取得する。 647 * 648 * @param joins List<TableStruct> 649 * @param table_name String 650 * @return 指定したテーブル 651 */ 652 private TableStruct search( final List<TableStruct> joins , final String table_name ) { 653 TableStruct join = null; 654 for(int i = 0; i < joins.size() ; i++){ 655 join = joins.get( i ); 656// if(join.equals(table_name)){ 657 if(join.equalTable(table_name)){ 658 return join; 659 }else{ 660 join = search(join.getJoinTables(),table_name); 661 } 662 } 663 return join; 664 } 665 } 666}