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.Attributes; 019 import java.util.List; 020 021 /** 022 * エレメントをあらわす、OGElement クラスを定義します? 023 * 024 * エレメント?、OGNode クラスを継承し?名称、属?、ノードリストを持つオブジェクトです? 025 * 通常で?ところの、タグになります? 026 * 属?は、OGAttributes クラスで管?ます?ノ?ドリス?に関する操作?、OGNodeクラスの実?す? 027 * 028 * OGNode は、enum OGNodeType で区別される状態を持って?す? 029 * OGNodeType は、それぞれ?再設定が可能です? 030 * 例えば、既存?エレメントやノ?ドに対して、コメントタイ?Comment)を指定すると? 031 * ファイル等への出力時にコメントとして出力されます? 032 * 033 * @og.rev 5.1.8.0 (2010/07/01) 新規作? 034 * 035 * @version 5.0 036 * @author Kazuhiko Hasegawa 037 * @since JDK6.0, 038 */ 039 public class OGElement extends OGNode { 040 // public static final String CR = System.getProperty("line.separator"); 041 042 // 5.2.1.0 (2010/10/01) nameSpace 対?og: ?mis:) 043 // 5.6.1.2 (2013/02/22) 個別に設定すべき?削除 044 /** 特殊:?部?、タグ属?の改行??行うタグ名? Stringを持って?す? **/ 045 // private static final String CR_SET = ":comment , :view , :select" ; 046 047 private final String qName ; // こ?タグの名前(nameSpace も含?レメント?名前) 048 // private final int paraCnt; // 階層(-1は階層なし?1は改行?み) 049 private OGAttributes attri = null; // 属?オブジェク? 050 051 // 階層に応じたスペ?スの設? 052 private static final int PARA_LEN = 8; 053 private static final String PARA_CHAR = "\t"; 054 private static final String[] PARA = new String[PARA_LEN]; 055 static { 056 PARA[0] = CR; 057 StringBuilder buf = new StringBuilder(); 058 buf.append( CR ); 059 for( int i=1; i<PARA_LEN; i++ ) { 060 buf.append( PARA_CHAR ); 061 PARA[i] = buf.toString(); 062 } 063 } 064 065 /** 066 * ノ?ド名を指定してのトコンストラクター 067 * 068 * ノ?ド名のみ?するため?属?と、ノードリストが空のエレメントを構築します? 069 * 070 * @param qName ノ?ド名 071 */ 072 public OGElement( final String qName ) { 073 this( qName,null ); 074 } 075 076 /** 077 * ノ?ド名と階層を指定してのトコンストラクター 078 * 079 * ノ?ド名のみを持つ、属?と、ノードリストが空のエレメントを構築します? 080 * 081 * @param qName ノ?ド名 082 * @param cnt 階層 083 */ 084 // public OGElement( final String qName , final int cnt ) { 085 // this( qName,(Attributes)null ); 086 // } 087 088 /** 089 * ノ?ド名を指定してのトコンストラクター 090 * 091 * ノ?ド名のみ?するため?属?と、ノードリストが空のエレメントを構築します? 092 * 093 * @og.rev 5.6.1.2 (2013/02/22) ? 094 * 095 * @param qName ノ?ド名 096 * @param attri 属?オブジェク? 097 */ 098 // public OGElement( final String qName , final OGAttributes attri ) { 099 // super(); 100 // setNodeType( OGNodeType.Element ); 101 // 102 // if( qName == null ) { 103 // String errMsg = "エレメントには、ノード名は??です?"; 104 // throw new RuntimeException( errMsg ); 105 // } 106 // 107 // boolean useCR = CR_SET.contains( qName ); 108 // if( useCR ) { attri.setUseCR( useCR ); } // true の場合?みセ?する? 109 // 110 // this.qName = qName; 111 // this.attri = attri ; 112 // this.paraCnt = -1 ; 113 // } 114 115 /** 116 * ノ?ド名、属?タブ?属?リストを?してのトコンストラクター 117 * 118 * 注?属?値の正規化は?行われます? 119 * 属?値に含まれるCR(復帰), LF(改?, TAB(タ?は?半角スペ?スに置き換えられます? 120 * XMLの規定では、属?の並び??保障されませんが?SAXのAttributesは、XMLに記述された?番で 121 * 取得できて?す?で、このクラスでの属?リストも、記述?の並び?なります? 122 * 123 * @og.rev 5.2.1.0 (2010/10/01) タグ属?の改行??、Set からString[] に変更? 124 * @og.rev 5.6.1.2 (2013/02/22) CR_SET を?列から文字?に変更 125 * 126 * @param qName ノ?ド名 127 * @param atts 属?リス? 128 */ 129 // public OGElement( final String qName , final String attTab , final Attributes atts , final int cnt ) { 130 public OGElement( final String qName , final Attributes atts ) { 131 super(); 132 setNodeType( OGNodeType.Element ); 133 134 if( qName == null ) { 135 String errMsg = "エレメントには、ノード名は??です?"; 136 throw new RuntimeException( errMsg ); 137 } 138 139 this.qName = qName; 140 // this.paraCnt = cnt ; 141 142 // 5.2.1.0 (2010/10/01) nameSpace の取得?CR_SET ?SetからString[] に変更? 143 // 5.6.1.2 (2013/02/22) 完???ではなく?indexOf の部???で反転するように変更? 144 // boolean useCR = CR_SET.contains( qName ); 145 146 // String attTab = getPara( paraCnt+1 ); 147 // this.attri = new OGAttributes( attTab , atts , useCR ) ; 148 this.attri = new OGAttributes( atts ) ; 149 } 150 151 /** 152 * ノ?ド名を返します? 153 * 154 * @return ノ?ド名 155 */ 156 public String getTagName() { 157 return qName; 158 } 159 160 /** 161 * 属?オブジェクトを返します? 162 * 163 * これは、org.xml.sax.Attributes ではなく?OGAttributes オブジェクトを返します? 164 * ?オブジェクトそのも?を返します?で、この OGAttributes の変更は、この 165 * エレメントが持つ?属?も変更されます? 166 * 167 * @return 属?オブジェク? 168 */ 169 public OGAttributes getOGAttributes() { 170 return attri; 171 } 172 173 /** 174 * 属?オブジェクトをセ?します? 175 * 176 * 属?オブジェクト?セ?は、このメソ?からのみできるようにします? 177 * ?オブジェクトそのも?にセ?します?で、異な?OGAttributes をセ?した??合?? 178 * 外部で、コピ?してからセ?してください? 179 * 180 * @og.rev 5.6.1.2 (2013/02/22) 新規追? 181 * 182 * @param attri 属?オブジェク?org.opengion.fukurou.xml.OGAttributes) 183 */ 184 public void setOGAttributes( final OGAttributes attri ) { 185 186 // boolean useCR = CR_SET.contains( qName ); 187 // attri.setUseCR( useCR ); 188 // String attTab = getPara( paraCnt+1 ); 189 // attri.setAttrTab( attTab ); 190 191 this.attri = attri; 192 } 193 194 /** 195 * 属?リストから?id属?の、属?値を取得します? 196 * 197 * id属? は、?部?キャ?ュしており、すぐに取り出せます? 198 * タグを特定する?合??属?のキーと値で選別するのではなく? 199 * id属?を付与して選別するようにすれば??に見つけることが可能になります? 200 * 201 * @og.rev 5.1.9.0 (2010/08/01) 新規追? 202 * 203 * @return id属?値 204 */ 205 public String getId() { 206 // return attri.getId() ; 207 return (attri != null) ? attri.getId() : null ; 208 } 209 210 /** 211 * 属?リストから???属?キーの、属?値を取得します? 212 * 213 * こ?処??、属?リストをすべてスキャンして、キーにマッチす? 214 * 属?オブジェクトを見つけ?そこから、属?値を取り?す?で? 215 * パフォーマンスに問題があります? 216 * 基本?は、アドレス?で、属?値を取り?すよ?してください? 217 * 218 * @og.rev 5.6.1.2 (2013/02/22) 新規追? 219 * 220 * @param key 属?キー 221 * 222 * @return 属?値 223 */ 224 public String getVal( final String key ) { 225 // return attri.getVal( key ); 226 return (attri != null) ? attri.getVal( key ) : null ; 227 } 228 229 /** 230 * 属?リストに、属?(キー、?のセ?)を設定します? 231 * 232 * 属?リスト???に、属?(キー、?のセ?)を設定します? 233 * 234 * @param key 属?リスト?キー 235 * @param val 属?リスト?値 236 */ 237 public void addAttr( final String key , final String val ) { 238 if( attri == null ) { attri = new OGAttributes() ; } 239 attri.add( key,val ) ; 240 } 241 242 /** 243 * 自??身の状態が、指定?条件に合?して?かど?、判定します? 244 * 245 * 合?して?場合?、true を?合?して???合?、false を返します? 246 * 247 * ??属??null の場合?、すべてに合?すると判断します? 248 * 例えば、kye のみ?すると、その属?名を持って?エレメントすべてで 249 * true が返されます? 250 * 実行?度を?えると、ノード名は?すべきです? 251 * 252 * @param name ノ?ド名 null の場合?、すべての ノ?ド名 に合? 253 * @param key 属??null の場合?、すべての 属??に合? 254 * @param val 属?値 null の場合?、すべての 属?値 に合? 255 * 256 * @return 条件がこのエレメントに合?した場?true 257 */ 258 public boolean match( final String name , final String key , final String val ) { 259 // name が存在するが?不??の場合?、false 260 if( name != null && ! name.equals( qName ) ) { return false; } 261 262 // attri ?null なのに、key ?val が?null でな??合?合?しな??で、false と判断 263 if( attri == null && ( key != null || val != null ) ) { return false; } 264 265 // キーが存在し?値も存在する場合?、その値の合?と同じ結果となる? 266 if( key != null ) { 267 if( val != null ) { return val.equals( attri.getVal( key ) ); } // 値があれ?、比?る? 268 else { return ( attri.getAdrs( key ) >= 0 ); } // 値がなければ、存在チェ? 269 } 270 271 // 値が存在する場合?、その値が含まれるかチェ?し?あれば、true, なければ false 272 if( val != null ) { 273 boolean flag = false; 274 int len = attri.size(); 275 for( int i=0; i<len; i++ ) { 276 if( val.equals( attri.getVal(i) ) ) { flag = true; break; } 277 } 278 return flag; 279 } 280 281 // 上記?条件以外?、すべて?null なので、true 282 return true; 283 } 284 285 /** 286 * 段落??を返します? 287 * 288 * 段落??は?層を表す文字?です? 289 * 通常は?AB ですが、XMLの階層が?PARA_LEN を?ても?段落を増やしません? 290 * 段落の??の??、改行です? 291 * 292 * @og.rev 5.6.1.2 (2013/02/22) ??ストがな??合?タグの終?にスペ?スは入れな?? 293 * @og.rev 5.6.4.4 (2013/05/31) PARA_LEN を?ても?段落を増やしません? 294 * 295 * @param cnt 階層(-1:なし? 296 * @return 段落?? 297 * @see OGNodeType 298 */ 299 private String getPara( final int cnt ) { 300 if( cnt < 0 ) { return ""; } 301 if( cnt < PARA_LEN ) { return PARA[cnt]; } 302 else { return PARA[PARA_LEN-1]; } // 5.6.4.4 (2013/05/31) PARA_LEN を?ても?段落を増やしません? 303 304 // StringBuilder buf = new StringBuilder(); 305 // buf.append( PARA[PARA_LEN-1] ); 306 // for( int i=PARA_LEN-1; i<cnt; i++ ) { 307 // buf.append( PARA_CHAR ); 308 // } 309 310 // return buf.toString(); 311 } 312 313 /** 314 * オブジェクト???表現を返します? 315 * 316 * ??は、OGNodeType により異なります? 317 * Comment ノ?ド?場合?、コメント記号を?Cdata ノ?ド?場合?、CDATA ? 318 * つけて出力します? 319 * 320 * @og.rev 5.6.1.2 (2013/02/22) ??ストがな??合?タグの終?にスペ?スは入れな?? 321 * @og.rev 5.6.4.4 (2013/05/31) 改行3つを改行2つに置換します? 322 * 323 * @param cnt Nodeの階層??1:なし?0:改行?み?:改行? "・・・・?? 324 * @return こ?オブジェクト???表現 325 * @see OGNode#toString() 326 */ 327 // public String toString() { 328 @Override 329 public String getText( final int cnt ) { 330 StringBuilder buf = new StringBuilder(); 331 332 buf.append( getPara(cnt) ); 333 buf.append( "<" ).append( qName ); 334 335 // boolean useCR = CR_SET.contains( qName ); 336 buf.append( attri.getText( getPara(cnt+1) ) ); 337 // if( useCR ) { buf.append( getPara(cnt) ); } 338 339 String text = super.getText(cnt+1); 340 341 if( text.trim().isEmpty() ) { 342 // buf.append( " />" ); 343 buf.append( "/>" ); // 5.6.1.2 (2013/02/22) タグの終?にスペ?スは入れな?? 344 } 345 else { 346 buf.append( ">" ).append( text ); 347 buf.append( getPara(cnt) ); 348 buf.append( "</" ).append( qName ).append( ">" ); 349 // buf.append( CR ); 350 } 351 String rtn = buf.toString(); 352 353 switch( getNodeType() ) { 354 case Comment: rtn = "<!-- " + rtn + " -->"; break; 355 case Cdata: rtn = "<![CDATA[ " + rtn + " ]]>"; break; 356 // case Text: 357 // case List: 358 default: break; 359 } 360 361 // return rtn ; 362 return rtn.replaceAll( CR+CR+CR , CR+CR ) ; // 改行3つを改行2つに置換します? 363 } 364 365 /** 366 * オブジェクト???表現を返します? 367 * 368 * ??は、OGNodeType により異なります? 369 * Comment ノ?ド?場合?、コメント記号を?Cdata ノ?ド?場合?、CDATA ? 370 * つけて出力します? 371 * 372 * @og.rev 5.6.1.2 (2013/02/22) ?。継承?処?? 373 * 374 * @return こ?オブジェクト???表現 375 * @see OGNode#toString() 376 */ 377 // @Override 378 // public String toString() { 379 // return getText(-10); 380 // } 381 }