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.hayabusa.report2;
017
018 import java.util.ArrayList;
019 import java.util.List;
020
021 import org.opengion.hayabusa.common.HybsSystemException;
022
023 /**
024 * Calc帳票シスãƒ?ƒ でタグのパã?スを行うためのクラスですã?
025 *
026 * 主に開始タグ、終äº?‚¿グを指定したパースのループå?ç�?‚’行うための機è?を提供しますã?
027 * 具体的には、{@link #doParse(String, String, String)}により、パースæ–?—å?ã€?–‹始タグ、終äº?‚¿グã‚?
028 * æŒ?®šし、パースを行いますã?
029 * パã?ス後ã?æ–?—å?は、{@link #doParse(String, String, String)}の戻りå?になりますã?
030 *
031 * パã?ス実行中に、発見された開始タグから終äº?‚¿グまでの間ã?æ–?—å?の処ç�??、{@link #exec(String, StringBuilder, int)}ã‚?
032 * オーバã?ライドすることにより定義しますã?
033 *
034 * またã?こã?クラスでは、パースにå¿?¦�なå�?¨®ユーãƒ?‚£リãƒ?‚£メソãƒ?ƒ‰につã�?�¦も同様に定義されてã�?�¾すã?
035 *
036 * @og.group 帳票シスãƒ?ƒ
037 *
038 * @version 4.0
039 * @author Hiroki.Nakamura
040 * @since JDK1.6
041 */
042 class TagParser {
043
044 private int preOffset = 0;
045 private int curOffset = 0;
046
047 /**
048 * パã?ス処ç�?‚’行いますã?
049 *
050 * パã?ス中に取り出された開始タグから終äº?‚¿グまでのæ–?—å?の処ç�??ã€?
051 * {@link #exec(String, StringBuilder, int)}で定義しますã?
052 *
053 * またã?isAddTagをtrueにした場合ã?{@link #exec(String, StringBuilder, int)}に渡されã‚?
054 * æ–?—å?にã€?–‹始タグ、終äº?‚¿グが含まれますã?
055 * é€?�«falseにした場合ã?ã€?–‹始タグ、終äº?‚¿グを除きã?{@link #exec(String, StringBuilder, int)}に渡されますã?
056 *
057 * @og.rev 5.2.2.0 (2010/11/01) 読み飛ã?しをした場合にã€?–‹始タグが書き込まれなã�?ƒ�グを修正
058 *
059 * @param content パã?ス対象æ–?—å?
060 * @param startTag 開始タグ
061 * @param endTag 終äº?‚¿グ
062 * @param isAddTag 開始タグ・終äº?‚¿グを含ã‚?�‹
063 *
064 * @return パã?ス後ã?æ–?—å?
065 * @see #exec(String, StringBuilder, int)
066 */
067 public String doParse( final String content, final String startTag, final String endTag, final boolean isAddTag ) {
068 StringBuilder buf = new StringBuilder();
069 String errMsg = null;
070
071 while( ( preOffset = content.indexOf( startTag, Math.max( preOffset, curOffset ) ) ) >= 0 ) {
072 buf.append( content.substring( curOffset, preOffset ) );
073 curOffset = content.indexOf( endTag, preOffset + startTag.length() );
074
075 if( checkIgnore( preOffset, curOffset ) ) {
076 if( curOffset < 0 ){
077 errMsg = "[ERROR]PARSE:開始タグを終äº?‚¿グの整合æ?が不正ですã?[開始タグ=" + startTag + ":終äº?‚¿グ=" + endTag + "]";
078 throw new HybsSystemException( errMsg );
079 }
080 preOffset += startTag.length();
081 curOffset += endTag.length();
082
083 String str = null;
084 if( isAddTag ) {
085 str = content.substring( preOffset - startTag.length(), curOffset );
086 }
087 else {
088 str = content.substring( preOffset, curOffset - endTag.length() );
089 }
090
091 exec( str, buf, curOffset );
092 }
093 else {
094 // 5.2.2.0 (2010/11/01) 開始タグが書き込まれなã�?ƒ�グを修正
095 buf.append( startTag );
096 preOffset += startTag.length();
097 curOffset = preOffset;
098 }
099 }
100 buf.append( content.substring( curOffset, content.length() ) );
101
102 return buf.toString();
103 }
104
105 /**
106 * パã?ス処ç�?‚’行いますã?
107 *
108 * 詳細は、{@link #doParse(String, String, String, boolean)}のJavadocを参照して下さã�??
109 *
110 * @param content パã?ス対象æ–?—å?
111 * @param startTag 開始タグ
112 * @param endTag 終äº?‚¿グ
113 *
114 * @return パã?ス後ã?æ–?—å?
115 * @see #doParse(String, String, String, boolean)
116 */
117 public String doParse( final String content, final String startTag, final String endTag ) {
118 return doParse( content, startTag, endTag, true );
119 }
120
121 /**
122 * 開始タグから終äº?‚¿グまでのæ–?—å?の処ç�?‚’定義しますã?
123 *
124 * こã?実è£?�§は、何も処ç�?‚’行いませんã€?åˆ?‚Š出したæ–?—å?はアペンドされません)
125 * サブクラスでオーバã?ライドして実際の処ç�?‚’実è£?�—て下さã�??
126 *
127 * @param str 開始タグから終äº?‚¿グまでのæ–?—å?(開始タグ・終äº?‚¿グを含ã‚?
128 * @param buf 出力を行うæ–?—å?バッファ
129 * @param offset 終äº?‚¿グのオフセãƒ?ƒˆ
130 */
131 protected void exec( final String str, final StringBuilder buf, final int offset ) {
132 // Document empty method 対ç?
133 }
134
135 /**
136 * 開始タグから終äº?‚¿グまでのæ–?—å?の処ç�?‚’実行するかどã�?�‹を定義しますã?
137 *
138 * falseが返された場合ã?何も処ç�?�•れず({@link #exec(String, StringBuilder, int)}が実行されなã�?ã€?
139 * å…??æ–?—å?がそのまま出力されますã?
140 *
141 * @param strOffset 開始タグのオフセãƒ?ƒˆ
142 * @param endOffset 終äº?‚¿グのオフセãƒ?ƒˆ
143 *
144 * @return 処ç�?‚’行うかどã�?�‹(true:処ç�?‚’行う false:処ç�?‚’行わなã�?
145 */
146 protected boolean checkIgnore( final int strOffset, final int endOffset ) {
147 return true;
148 }
149
150 /**
151 * パã?ス実行中のoffset値を外部からセãƒ?ƒˆしますã?
152 *
153 * こã?メソãƒ?ƒ‰は、{@link #exec(String, StringBuilder, int)}で、å?ç�?µ�果により、offset値ã‚?
154 * 進めておくå¿?¦�がある場合に利用されますã?(つまりé?常は利用するå¿?¦�ã?ありません)
155 *
156 * @param offset オフセãƒ?ƒˆ
157 * @see #exec(String, StringBuilder, int)
158 */
159 public void setOffset( final int offset ) {
160 curOffset = offset;
161 }
162
163 /**
164 * 引数のæ–?—å?を指定された開始タグ、終äº?‚¿グで解析し配å?として返す、ユーãƒ?‚£リãƒ?‚£メソãƒ?ƒ‰ですã?
165 *
166 * 開始タグより前ã?æ–?—å?は0番目に、終äº?‚¿グより後ã?æ–?—å?は1番目に格納されますã?
167 * 2番目以降にã€?–‹始タグ、終äº?‚¿グの部åˆ?�Œ格納されますã?
168 *
169 * @param str 解析する文字å?
170 * @param startTag 開始タグ
171 * @param endTag 終äº?‚¿グ
172 *
173 * @return 解析結果の配å?
174 */
175 public static String[] tag2Array( final String str, final String startTag, final String endTag ) {
176 String header = null;
177 String footer = null;
178 List<String> body = new ArrayList<String>();
179
180 int preOffset = -1;
181 int curOffset = 0;
182
183 while( true ) {
184 curOffset = str.indexOf( startTag, preOffset + 1 );
185 if( curOffset < 0 ) {
186 curOffset = str.lastIndexOf( endTag ) + endTag.length();
187 body.add( str.substring( preOffset, curOffset ) );
188
189 footer = str.substring( curOffset );
190 break;
191 }
192 else if( preOffset == -1 ) {
193 header = str.substring( 0, curOffset );
194 }
195 else {
196 body.add( str.substring( preOffset, curOffset ) );
197 }
198 preOffset = curOffset;
199 }
200
201 String[] arr = new String[body.size()+2];
202 arr[0] = header;
203 arr[1] = footer;
204 for( int i=0; i<body.size(); i++ ) {
205 arr[i+2] = body.get(i);
206 }
207
208 return arr;
209 }
210
211 /**
212 * 引数のæ–?—å?の開始文字と終äº?–‡字ã?間ã?æ–?—å?を取りå?すã?ユーãƒ?‚£リãƒ?‚£メソãƒ?ƒ‰ですã?
213 * ※返されるæ–?—å?にã€?–‹始文字ã?終äº?–‡字ã?含まれませんã€?
214 *
215 * @param str 解析する文字å?
216 * @param start 開始文å?
217 * @param end 終äº?–‡å?
218 *
219 * @return 解析結果のæ–??
220 */
221 public static String getValueFromTag( final String str, final String start, final String end ) {
222 int startOffset = str.indexOf( start );
223 // int startOffset = str.indexOf( start ) + start.length();
224 // 4.2.4.0 (2008/06/02) 存在しなã�??合ã?nullで返す
225 if( startOffset == -1 ) {
226 return null;
227 }
228 startOffset += start.length();
229
230 int endOffset = str.indexOf( end, startOffset );
231 String value = str.substring( startOffset, endOffset );
232
233 return value;
234 }
235
236 /**
237 * 引数のキーから不要なキーを取り除くã?ユーãƒ?‚£リãƒ?‚£メソãƒ?ƒ‰ですã?
238 *
239 * @og.rev 5.1.8.0 (2010/07/01) spanタグを削除
240 *
241 * @param key オリジナルのキー
242 * @param sb キーの外に含まれるaタグを削除するための、バãƒ?ƒ•ァ
243 *
244 * @return 削除後ã?キー
245 */
246 public static String checkKey( final String key, final StringBuilder sb ) {
247 if( key.indexOf( '<' ) < 0 && key.indexOf( '>' ) < 0 ) { return key; }
248
249 StringBuilder rtn = new StringBuilder( key );
250 String tagEnd = ">";
251 int rtnOffset = -1;
252
253 // <text:a ...>{@XXX</text:a>の不要タグを削除
254 String delTagStart1 = "<text:a ";
255 String delTagEnd1 = "</text:a>";
256 while( ( rtnOffset = rtn.lastIndexOf( delTagEnd1 ) ) >= 0 ) {
257 boolean isDel = false;
258 // キー自身に含まれるaタグを削除
259 int startOffset = rtn.lastIndexOf( delTagStart1, rtnOffset );
260 if( startOffset >= 0 ) {
261 int endOffset = rtn.indexOf( tagEnd, startOffset );
262 if( endOffset >= 0 ) {
263 rtn.delete( rtnOffset, rtnOffset + delTagEnd1.length() );
264 rtn.delete( startOffset, endOffset + tagEnd.length() );
265 isDel = true;
266 }
267 }
268 else {
269 // キーの外に含まれるaタグを削除
270 startOffset = sb.lastIndexOf( delTagStart1 );
271 if( startOffset >= 0 ) {
272 int endOffset = sb.indexOf( tagEnd, startOffset );
273 if( endOffset >= 0 ) {
274 rtn.delete( rtnOffset, rtnOffset + delTagEnd1.length() );
275 sb.delete( startOffset, endOffset + tagEnd.length() );
276 isDel = true;
277 }
278 }
279 }
280 if( !isDel ) { break; }
281 }
282
283 // 5.1.8.0 (2010/07/01) spanタグを削除
284 String delTagStart2 = "<text:span ";
285 String delTagEnd2 = "</text:span>";
286 while( ( rtnOffset = rtn.lastIndexOf( delTagEnd2 ) ) >= 0 ) {
287 boolean isDel = false;
288 // キー自身に含まれるspanタグを削除
289 int startOffset = rtn.lastIndexOf( delTagStart2, rtnOffset );
290 if( startOffset >= 0 ) {
291 int endOffset = rtn.indexOf( tagEnd, startOffset );
292 if( endOffset >= 0 ) {
293 rtn.delete( rtnOffset, rtnOffset + delTagEnd2.length() );
294 rtn.delete( startOffset, endOffset + tagEnd.length() );
295 isDel = true;
296 }
297 }
298 else {
299 // キーの外に含まれるspanタグを削除
300 startOffset = sb.lastIndexOf( delTagStart2 );
301 if( startOffset >= 0 ) {
302 int endOffset = sb.indexOf( tagEnd, startOffset );
303 if( endOffset >= 0 ) {
304 rtn.delete( rtnOffset, rtnOffset + delTagEnd2.length() );
305 sb.delete( startOffset, endOffset + tagEnd.length() );
306 isDel = true;
307 }
308 }
309 }
310 if( !isDel ) { break; }
311 }
312
313 return rtn.toString();
314 }
315 }
316