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 }