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.io.BufferedReader;
019 import java.io.BufferedWriter;
020 import java.io.File;
021 import java.io.FileInputStream;
022 import java.io.FileNotFoundException;
023 import java.io.FileOutputStream;
024 import java.io.IOException;
025 import java.io.InputStreamReader;
026 import java.io.OutputStreamWriter;
027 import java.io.UnsupportedEncodingException;
028 import java.nio.channels.FileChannel;
029 import java.util.ArrayList;
030 import java.util.HashMap;
031 import java.util.List;
032 import java.util.Locale;
033 import java.util.Map;
034 import java.util.Set;
035
036 import org.opengion.fukurou.model.NativeType;
037 import org.opengion.fukurou.util.Closer;
038 import org.opengion.fukurou.util.FileUtil;
039 import org.opengion.fukurou.util.QrcodeImage;
040 import org.opengion.hayabusa.common.HybsSystem;
041 import org.opengion.hayabusa.common.HybsSystemException;
042
043 /**
044 * æŒ?®šされたパスに存在するODSの各XMLファイルをパースしã?帳票定義及ã?
045 * 帳票ãƒ??タから書き換えますã?
046 * 書き換えã?読み取り先と同じファイルであるため、ä¸?—¦読み取った各XMLã‚?
047 * メモリ上に格納したからパース後ã?XMLファイルの書き込みを行いますã?
048 *
049 * パã?ス対象となるファイルは以下ã?3つですã?
050 * content.xml シートã?中身を定義
051 * meta.xml メタãƒ??タを定義
052 * style.xml 帳票ヘッãƒ??フッターを定義
053 *
054 * content.xmlのパã?ス処ç�?�¨して、まずxmlファイルをシーãƒ?行単位にåˆ?§£しますã?
055 * そã?後ã?åˆ?§£された行毎に帳票ãƒ??タを埋め込み、å?力å?のXMLに書き込みを行いますã?
056 * 書き込みは行単位に行われますã?
057 *
058 * またã?Calcの特性としてã€?–¢数の引数に不正な引数が指定された場合ã?(Text関数の
059 * 引数にnullが指定された場合ç?、エラー:XXXとã�?�†æ–?—が表示されますã?
060 * ここでは、これを回避するため、å?ての関数にisError関数を埋め込み、エラー表示ã‚?
061 * 行わなã�?‚ˆã�?�«してã�?�¾すã?
062 *
063 * @og.group 帳票シスãƒ?ƒ
064 *
065 * @version 4.0
066 * @author Hiroki.Nakamura
067 * @since JDK1.6
068 */
069 class OdsContentParser {
070
071 //======== content.xmlのパã?スで使用 ========================================
072 /* シートã?開始終äº?‚¿グ */
073 private static final String BODY_START_TAG = "<table:table ";
074 private static final String BODY_END_TAG = "</table:table>";
075
076 /* 行ã?開始終äº?‚¿グ */
077 private static final String ROW_START_TAG = "<table:table-row ";
078 // private static final String ROW_END_TAG = "</table:table-row>";
079
080 /* ペã?ジエンドカãƒ?ƒˆの際に、行を非表示にするためのãƒ??ブル宣è¨?*/
081 private static final String ROW_START_TAG_INVISIBLE = "<table:table-row table:visibility=\"collapse\" ";
082
083 /* セルの開始タグ */
084 private static final String TABLE_CELL_START_TAG = "<table:table-cell";
085 private static final String TABLE_CELL_END_TAG = "</table:table-cell>";
086
087 /* シート名を取得するためã?開始終äº?–‡å?*/
088 private static final String SHEET_NAME_START = "table:name=\"";
089 // private static final String SHEET_NAME_END = "\"";
090
091 /* オブジェクトã?終äº?½�置(シート名)を見つけるための開始文å?*/
092 private static final String OBJECT_SEARCH_STR = "table:end-cell-address=\"";
093
094 /* 印刷ç¯?›²æŒ?®šã?開始終äº?–‡å?*/
095 // 4.3.3.5 (2008/11/08) 空白ペã?ジ対策で追åŠ?
096 private static final String PRINT_RANGE_START = "table:print-ranges=\"";
097 private static final String PRINT_RANGE_END = "\"";
098
099 /* 表紙印刷用のペã?ジ名称 */
100 private static final String FIRST_PAGE_NAME = "FIRST";
101
102 /* シートブレイク用のキー 5.1.7.0 (2010/06/01) */
103 private static final String SHEET_BREAK = "SHEETBREAK";
104
105 /* 変数定義の開始終äº?–‡字及び区åˆ?‚Šæ–??*/
106 private static final String VAR_START = "{@";
107 private static final String VAR_END = "}";
108 private static final String VAR_CON = "_";
109
110 /* ペã?ジエンドカãƒ?ƒˆのカラãƒ?–‡字å? */
111 private static final String PAGE_END_CUT = "PAGEENDCUT";
112
113 /* ペã?ジブレイクのカラãƒ?–‡字å? */
114 private static final String PAGE_BREAK = "PAGEBREAK";
115
116 // /* ラインコピã?æ–?—å? 5.0.0.2 (2009/09/15) */
117 // private static final String LINE_COPY = "LINECOPY";
118
119 /* ペã?ジ番号出力用æ–?—å? 5.1.6.0 (2010/05/01) */
120 private static final String PAGE_NO= "PAGENO";
121
122 /* 行番号出力用æ–?—å? 5.1.6.0 (2010/05/01) */
123 private static final String ROW_NO= "ROWNO";
124
125 /* 画像ã?リンクを取得するためã?開始終äº?–‡å?*/
126 private static final String DRAW_IMG_START_TAG = "<draw:image xlink:href=\"";
127 private static final String DRAW_IMG_END_TAG = "</draw:image>";
128 private static final String DRAW_IMG_HREF_END = "\"";
129
130 /* 画像ファイルを保存するためã?パス */
131 private static final String IMG_DIR = "Pictures";
132
133 /* QRコードを処ç�?�™るためã?カラãƒ?�� */
134 private static final String QRCODE_PREFIX = "QRCODE.";
135
136 /* 作æ?したQRコードã?フォルãƒ?��及ã?拡張å?*/
137 private static final String QRCODE_FILETYPE = ".png";
138
139 /* 4.3.3.5 (2008/11/08) 動的に画像を入れ替えるためのパスを記述するカラãƒ?�� */
140 private static final String IMG_PREFIX = "IMG.";
141
142 /* ファンクション定義を見つけるための開始終äº?–‡å?*/
143 private static final String OOOC_FUNCTION_START = "oooc:=";
144 private static final String OOOC_FUNCTION_START_3 = "of:="; // 4.3.7.2 (2009/06/15) ODS仕様変更につき追åŠ?
145 // private static final String OOOC_FUNCTION_END = "\"";
146 private static final String OOOC_FUNCTION_END = ")\" ";
147
148 /* セルå†??改行を定義するæ–?—å? 5.0.2.0 (2009/11/01) */
149 private static final String OOO_CR = "</text:p><text:p>";
150
151 /* グラフオブジェクトã?書き換えを行うための開始終äº?–‡å?5.1.8.0 (2010/07/01) */
152 private static final String GRAPH_START_TAG = "<draw:frame ";
153 private static final String GRAPH_END_TAG = "</draw:frame>";
154 /* グラフã?ç¯?›²æŒ?®šã?書き換えを行うための開始終äº?–‡å?5.1.8.0 (2010/07/01) */
155 private static final String GRAPH_UPDATE_RANGE_START = "draw:notify-on-update-of-ranges=\"";
156 private static final String GRAPH_UPDATE_RANGE_END = "\"";
157 /* グラフã?オブジェクトへのリンクの書き換えを行うための開始終äº?–‡å?5.1.8.0 (2010/07/01) */
158 private static final String GRAPH_HREF_START = "xlink:href=\"./";
159 private static final String GRAPH_HREF_END = "\"";
160 private static final String GRAPH_OBJREPL = "ObjectReplacements";
161 /* グラフã?オブジェクト毎ã?content.xmlに記述してあるシート名の書き換えを行うための開始終äº?–‡å?5.1.8.0 (2010/07/01) */
162 private static final String GRAPH_CONTENT_START = "-address=\"";
163 private static final String GRAPH_CONTENT_END = "\"";
164 /* 生æ?したグラフã?オブジェクトをMETA-INF/manifest.xmlに登録するための開始終äº?–‡字å? 5.1.8.0 (2010/07/01) */
165 private static final String MANIFEST_START_TAG = "<manifest:file-entry ";
166 private static final String MANIFEST_END_TAG = "/>";
167
168 /* 数値タイプ置き換え用のæ–?—å? 5.1.8.0 (2010/07/01) */
169 private static final String TABLE_CELL_STRING_TYPE = "office:value-type=\"string\"";
170 private static final String TABLE_CELL_FLOAT_TYPE = "office:value-type=\"float\"";
171 private static final String TABLE_CELL_FLOAT_VAL_START = "office:value=\"";
172 private static final String TABLE_CELL_FLOAT_VAL_END = "\"";
173
174 /* ãƒ?‚スト文字å?の開始終äº?–‡字å? 5.1.8.0 (2010/07/01) */
175 private static final String TEXT_START_TAG = "<text:p>";
176 private static final String TEXT_END_TAG = "</text:p>";
177
178 /* コメンãƒ?アノテーション)をå?ç�?�™るためã?カラãƒ?�� 5.1.8.0 (2010/07/01) */
179 private static final String ANNOTATION_PREFIX = "ANO.";
180 private static final String TEXT_START_ANO_TAG = "<text:p"; // アノテーションの場合ã?置き換えを
181 private static final String TEXT_START_END_ANO_TAG = ">"; // アノテーションの場合ã?置き換えを
182
183 /* コメンãƒ?アノテーション)の開始ã?終äº?‚¿グ 5.1.8.0 (2010/07/01) */
184 private static final String ANNOTATION_START_TAG = "<office:annotation";
185 private static final String ANNOTATION_END_TAG = "</office:annotation>";
186
187 /* オブジェクトを検索するためのæ–?—å? 5.1.8.0 (2010/07/01) */
188 private static final String DRAW_START_KEY = "<draw:";
189 private static final String DRAW_END_KEY = "</draw:";
190
191 /* シートã?開始終äº?‚¿グ 5.2.2.0 (2010/11/01) */
192 private static final String STYLE_START_TAG = "<style:style ";
193 private static final String STYLE_END_TAG = "</style:style>";
194
195 /* シート名称 5.2.2.0 (2010/11/01) */
196 private static final String STYLE_NAME_START_TAG = "style:name=\"";
197 private static final String STYLE_NAME_END_TAG = "\"";
198
199 /* ãƒ??ブルå†?‚·ート名称 5.2.2.0 (2010/11/01) */
200 private static final String TABLE_STYLE_NAME_START_TAG = "table:style-name=\"";
201 private static final String TABLE_STYLE_NAME_END_TAG = "\""; // 5.6.3.1 (2013/04/05)
202
203 //===========================================================================
204
205 //======== meta.xmlのパã?スで使用 ===========================================
206 /* 総シートカウント数 */
207 private static final String TABLE_COUNT_START_TAG = "meta:table-count=\"";
208 private static final String TABLE_COUNT_END_TAG = "\"";
209
210 /* 総セルカウント数 */
211 private static final String CELL_COUNT_START_TAG = "meta:cell-count=\"";
212 private static final String CELL_COUNT_END_TAG = "\"";
213
214 /* 総オブジェクトカウント数 */
215 private static final String OBJECT_COUNT_START_TAG = "meta:object-count=\"";
216 private static final String OBJECT_COUNT_END_TAG = "\"";
217 //===========================================================================
218
219 /*
220 * 処ç�?¸の行番号の状æ…?
221 * NORMAL : 通常
222 * LASTROW : æœ?µ‚è¡?
223 * OVERFLOW : 終äº?
224 */
225 private static final int NORMAL = 0;
226 private static final int LASTROW = 1;
227 private static final int OVERFLOW = 2;
228 private int status = NORMAL;
229
230 /*
231 * å�?››形ファイルをå?ç�?�™る際の基準となる行数
232 * 初期>0 2è¡?{@XXX_1}まで)処ç�?¾?2 ・・・
233 * å�?››形で定義されてã�?‚‹行番号 + [baseRow] の値がDBTableModel上ã?行番号に相当すã‚?
234 * currentMaxRowはå�?‚·ートå?ç�?¾Œã?[baseRow]と同じ
235 */
236 private int currentBaseRow = 0;
237 private int currentMaxRow = 0;
238
239 /* 処ç�?�—たã?ージ数 */
240 private int pages = 0;
241
242 /* 処ç�?¡Œがペã?ジエンドカãƒ?ƒˆの対象かどã�?�‹ */
243 private boolean isPageEndCut = false; // 4.3.1.1 (2008/08/23) ローカル変数åŒ?
244
245 /* ペã?ジブレイクの処ç�?¸かどã�?�‹ */
246 private boolean isPageBreak = false;
247
248 /* XML宣è¨??æ–?—å?。各XMLで共通なのでクラス変数として定義 */
249 private String xmlHeader = null;
250
251 /* シートブレイク対象かどã�?�‹ 5.1.7.0 (2010/06/01) */
252 private int sheetBreakClm = -1;
253
254 /* シートã?ヘッãƒ??部åˆ??再パースを行うかどã�?�‹ 5.2.2.0 (2010/11/01) */
255 private boolean isNeedsReparse = false;
256
257 /* ペã?ジ名ã?マッピング(å…??シート名に対する新しいシート名) 5.2.2.0 (2010/11/01) */
258 private final Map<String,List<String>> pageNameMap = new HashMap<String,List<String>>();
259
260 /* ペã?ジ名に依存してã�?‚‹スタイル名称のリスãƒ?5.2.2.0 (2010/11/01) */
261 private final List<String> repStyleList = new ArrayList<String>();
262
263 /* manifest.xmlに追åŠ?�Œå¿?¦�なオブジェクトã?マッãƒ?5.3.1.0 (2011/01/01) */
264 private final Map<String,String> addObjs = new HashMap<String,String>();
265
266 private final ExecQueue queue;
267 private final String path;
268
269 /**
270 * コンストラクタ
271 *
272 * @og.rev 5.1.2.0 (2010/01/01) 処ç�?�—た行数をQueueオブジェクトから取å¾?シート数ã�?56をè¶?�ˆたå?合ã?対å¿?
273 *
274 * @param qu ExecQueue
275 * @param pt String
276 */
277 OdsContentParser( final ExecQueue qu, final String pt ) {
278 queue = qu;
279 path = pt;
280
281 currentBaseRow = queue.getExecRowCnt();
282 }
283
284 /**
285 * パã?ス処ç�?‚’実行しまã�?
286 *
287 * @og.rev 5.2.2.0 (2010/11/01) 条件付書式対å¿?
288 * @og.rev 5.3.1.0 (2011/01/01) OpenOffice3.2対å¿?追åŠ?�—た画像をmanifest.xmlに登録する
289 */
290 public void exec() {
291 /*
292 * 雛形ヘッãƒ??フッターの定義
293 * OOoではペã?ジ毎にヘッãƒ??フッターが設定できなã�?‚ˆã�??
294 * なので、å?てヘッãƒ??扱ã�?�§処ç�?
295 */
296 execStyles();
297
298 /* 中身の変換 */
299 execContent();
300
301 /* ヘッãƒ??部åˆ?�«シート情報があるå?合に書き換ã�?*/
302 if( isNeedsReparse ) {
303 /* ヘッãƒ??ファイルの再パース */
304 execContentHeader();
305 /* ヘッãƒ??ファイルとそれ以降ã?ファイルの連çµ?*/
306 execMergeContent();
307 }
308
309 /* メタãƒ??タの変換 */
310 execMeta();
311
312 // 5.3.1.0 (2011/01/01) OpenOffice3.2対å¿?追åŠ?�—た画像をmanifest.xmlに登録する
313 /* 追åŠ?�—た画像ã?オブジェクトをmanifest.xmlに追åŠ?*/
314 if( addObjs.size() > 0 ) {
315 execManifest();
316 }
317 }
318
319 /**
320 * 帳票処ç�?‚ューをå?に、content.xmlを書き換えますã?
321 * まずã?XMLをä¸?—¦メモリ上に展開した後ã?シート単位にåˆ?§£しã?ãƒ??タの埋め込みを行いますã?
322 *
323 * @og.rev 4.3.0.0 (2008/07/18) ペã?ジ数ã�?56をè¶?�ˆたå?合ã?エラー処ç�?
324 * @og.rev 5.0.0.2 (2009/09/15) LINECOPY機è?追åŠ?
325 * @og.rev 5.1.2.0 (2010/01/01) 処ç�?�—たã?ージ数、行数をQueueオブジェクトにセãƒ?ƒˆ(シート数ã�?56をè¶?�ˆたå?合ã?対å¿?
326 * @og.rev 5.1.7.0 (2010/06/01) è¤?•°シート対å¿?
327 * @og.rev 5.2.2.0 (2010/11/01) 条件付書式対å¿?
328 */
329 private void execContent() {
330 String fileName = path + "content.xml";
331 String content = readOOoXml( fileName );
332 // ファイルの解析し、シーãƒ?行単位にåˆ?§£
333 String[] tags = tag2Array( content, BODY_START_TAG, BODY_END_TAG );
334
335 // 5.2.2.0 (2010/11/01) 条件付書式対å¿?
336 // content.xmlのヘッãƒ??部åˆ??み書きå?ã�?
337 String contentHeader = tags[0];
338 BufferedWriter bw = null;
339 try {
340 bw = getWriter( fileName );
341 bw.write( xmlHeader );
342 bw.write( '\n' );
343 bw.write( contentHeader );
344 bw.flush();
345 }
346 catch ( IOException ex ) {
347 queue.addMsg( "[ERROR]PARSE:error occurer while content.xml(header) " + fileName + HybsSystem.CR );
348 throw new HybsSystemException( ex );
349 }
350 finally {
351 Closer.ioClose( bw );
352 bw = null;
353 }
354
355 String contentFooter = tags[1];
356 List<OdsSheet> firstSheets = new ArrayList<OdsSheet>();
357 Map<String, OdsSheet> sheets = new HashMap<String,OdsSheet>();
358 OdsSheet defaultSheet = null;
359 for( int i = 2; i < tags.length; i++ ) {
360 OdsSheet sheet = new OdsSheet();
361 // sheet.analyze( tags[i] );
362 sheet.analyze( tags[i],queue.getBody().getRowCount() ); // 5.0.0.2 (2009/09/15)
363 // sheets.add( sheet );
364 // 5.1.7.0 (2010/06/01) è¤?•°シート対å¿?
365 String sheetName = sheet.getSheetName();
366 if( sheetName.startsWith( FIRST_PAGE_NAME ) ) {
367 firstSheets.add( sheet );
368 }
369 else {
370 sheets.put( sheetName, sheet );
371 // ä¸?•ª初めに見つかった表紙以外ã?シートをãƒ?ƒ•ォルトシートとして設å®?
372 if( defaultSheet == null ) {
373 defaultSheet = sheet;
374 }
375 }
376
377 // 5.2.2.0 (2010/11/01) 条件付書式対å¿?
378 if( !isNeedsReparse && contentHeader.indexOf( "=\"" + sheet.getOrigSheetName() + "." ) >= 0 ) {
379 isNeedsReparse = true;
380 }
381
382 // 5.2.2.0 (2010/11/01) 条件付書式対å¿?
383 pageNameMap.put( sheet.getOrigSheetName(), new ArrayList<String>() );
384 }
385
386 // content.xmlの書きå?ã�?
387 // BufferedWriter bw = null;
388 try {
389 // 5.2.2.0 (2010/11/01) 条件付書式対å¿?
390 // bw = getWriter( fileName );
391 if( isNeedsReparse ) {
392 // ヘッãƒ??をå?パã?スする場合ã?、ã?ãƒ?‚£部åˆ?‚’
393 // content.xml.tmpに書きå?して、後でマã?ジする
394 bw = getWriter( fileName + ".tmp" );
395 getRepStyleList( contentHeader );
396 }
397 else {
398 // ヘッãƒ??をå?パã?スすしなã�??合ã?、ã?ãƒ?‚£部åˆ?‚’
399 // content.xml追åŠ?ƒ¢ードで書き込みする
400 bw = getWriter( fileName, true );
401 }
402
403 // bw.write( xmlHeader );
404 // bw.write( '\n' );
405 // // ヘッãƒ??
406 // bw.write( contentHeader );
407
408 // 表紙ã?ージの出åŠ?
409 if( queue.getExecPagesCnt() == 0 ) {
410 for ( OdsSheet firstSheet : firstSheets ) {
411 if ( currentBaseRow >= queue.getBody().getRowCount() ) {
412 break;
413 }
414 writeParsedSheet( firstSheet, bw );
415 }
416 }
417
418 // 5.1.7.0 (2010/06/01) è¤?•°シート対å¿?
419 sheetBreakClm = queue.getBody().getColumnNo( SHEET_BREAK, false );
420
421 // 繰り返しペã?ジの出åŠ?
422 while ( currentBaseRow < queue.getBody().getRowCount() ) {
423 // 4.3.0.0 (2008/07/18) ペã?ジ数ã�?56をè¶?�ˆたå?合にエラーとする
424 // 5.1.2.0 (2010/01/01) 256シートをè¶?�ˆたå?合ã?対å¿?
425 // if( pages >= 256 ){
426 if( pages >= ExecQueue.MAX_SHEETS_PER_FILE ) {
427 // queue.addMsg( "[ERROR]PARSE:シート数ã�?56枚をè¶?�ˆましたã€? + HybsSystem.CR );
428 // throw new HybsSystemException();
429 queue.setEnd( false );
430 break;
431 }
432
433 OdsSheet sheet = null;
434 if( sheetBreakClm >= 0 ) {
435 String sheetName = queue.getBody().getValue( currentBaseRow, sheetBreakClm );
436 if( sheetName != null && sheetName.length() > 0 ) {
437 sheet = sheets.get( sheetName );
438 }
439 }
440 if( sheet == null ) { sheet = defaultSheet; }
441
442 writeParsedSheet( sheet, bw );
443 }
444
445 // 5.1.2.0 (2010/01/01) 256シートをè¶?�ˆたå?合ã?対å¿?
446 queue.addExecPageCnt( pages );
447 queue.setExecRowCnt( currentBaseRow );
448
449 // フッター
450 bw.write( contentFooter );
451 bw.flush();
452 }
453 catch ( IOException ex ) {
454 queue.addMsg( "[ERROR]PARSE:error occurer while write Parsed Sheet " + fileName + HybsSystem.CR );
455 throw new HybsSystemException( ex );
456 }
457 finally {
458 Closer.ioClose( bw );
459 }
460 }
461
462 /**
463 * シート単位にパã?スされた文書ãƒ??タを書き込みまã�?
464 * 出力されるシート名には、ã?ージ番号と基底となる行番号をセãƒ?ƒˆしますã?
465 *
466 * @og.rev 4.2.4.0 (2008/07/04) 行単位にファイルに書き込ã‚?‚ˆã�?�«変更
467 * @og.rev 5.2.0.0 (2010/09/01) 表紙ã?場合ã?、BODY部åˆ??ãƒ??タが含まれてã�?�ªくてもOK
468 * @og.rev 5.2.1.0 (2010/10/01) シート名定義対å¿?
469 * @og.rev 5.2.2.0 (2010/11/01) 条件付書式対å¿?
470 *
471 * @param sheet
472 * @param bw
473 * @throws IOException 書き込みに失敗したå?å�?
474 */
475 private void writeParsedSheet( final OdsSheet sheet, final BufferedWriter bw ) throws IOException {
476 // シート名
477 // String outputSheetName = "Page" + pages + "_" + "Row" + currentBaseRow + "";
478 String outputSheetName = null;
479 if( sheet.getConfSheetName() == null ) {
480 outputSheetName = "Page" + ( queue.getExecPagesCnt() + pages ) + "_" + "Row" + currentBaseRow + "";
481 }
482 else {
483 outputSheetName = sheet.getConfSheetName() + ( queue.getExecPagesCnt() + pages + 1 );
484 }
485
486 // ペã?ジブレイク変数をå?期化
487 isPageBreak = false;
488
489 // シートã?ヘッãƒ??部åˆ?‚’書き込み(シート名も書き換ã�?
490 // String headerStr = sheet.getHeader().replace( SHEET_NAME_START + sheet.getSheetName(), SHEET_NAME_START + outputSheetName );
491 String headerStr = sheet.getHeader().replace( SHEET_NAME_START + sheet.getOrigSheetName(), SHEET_NAME_START + outputSheetName );
492
493 // 印刷ç¯?›²æŒ?®š部åˆ??シート名を変更
494 // 4.3.3.5 (2008/11/08) 空白ペã?ジ出力ã?対策ã?印刷ç¯?›²のシート名書き換えを追åŠ?
495 int printRangeStart = headerStr.indexOf( PRINT_RANGE_START );
496 if( printRangeStart >= 0 ) {
497 int printRangeEnd = headerStr.indexOf( PRINT_RANGE_END, printRangeStart + PRINT_RANGE_START.length() );
498 String rangeStr = headerStr.substring( printRangeStart, printRangeEnd );
499 // rangeStr = rangeStr.replace( sheet.getSheetName(), outputSheetName );
500 rangeStr = rangeStr.replace( sheet.getOrigSheetName(), outputSheetName );
501 headerStr = headerStr.substring( 0, printRangeStart ) + rangeStr + headerStr.substring( printRangeEnd );
502 }
503
504 bw.write( headerStr );
505
506 // シートã?ボディ部åˆ?‚’書き込み
507 String[] rows = sheet.getRows();
508 for( int i = 0; i < rows.length; i++ ) {
509 // 4.3.4.4 (2009/01/01)
510 // writeParsedRow( rows[i], bw, sheet.getSheetName(), outputSheetName );
511 writeParsedRow( rows[i], bw, sheet.getOrigSheetName(), outputSheetName );
512 }
513 // {@XXXX}が埋め込まれてã�?�ªã�??合ã?エラー
514 // 5.2.0.0 (2010/09/01) 表紙ã?場合ã?、BODY部åˆ??ãƒ??タが含まれてã�?�ªくてもOK
515 // if( currentBaseRow == currentMaxRow ) {
516 // if( currentBaseRow == currentMaxRow && !sheet.getSheetName().startsWith( FIRST_PAGE_NAME ) ) {
517 if( currentBaseRow == currentMaxRow && !sheet.getOrigSheetName().startsWith( FIRST_PAGE_NAME ) ) {
518 queue.addMsg( "[ERROR]PARSE:No Data defined on Template ODS(" + queue.getListId() + ")" + HybsSystem.CR );
519 throw new HybsSystemException();
520 }
521 currentBaseRow = currentMaxRow;
522
523 // シートã?フッター部åˆ?‚’書き込み
524 bw.write( sheet.getFooter() );
525
526 pages++;
527
528 // 5.2.2.0 (2010/11/01) 条件付書式対å¿?
529 pageNameMap.get( sheet.getOrigSheetName() ).add( outputSheetName );
530 }
531
532 /**
533 * 行単位にパã?スされた文書ãƒ??タを書き込みまã�?
534 *
535 * @og.rev 4.2.3.1 (2008/06/19) 関数エラーを表示させなã�?�Ÿめã?ISERROR関数を埋め込み
536 * @og.rev 4.2.4.0 (2008/07/04) 行単位にファイルに書き込ã‚?‚ˆã�?�«変更
537 * @og.rev 4.3.0.0 (2008/07/17) ?›ï¼?�¨?�ã?整合æ?チェãƒ?‚¯追åŠ?
538 * @og.rev 4.3.0.0 (2008/07/22) 行最後ã??›ï¼?½�整合æ?エラーハンドリング追åŠ?
539 * @og.rev 4.3.3.5 (2008/11/08) 画像ã?動的な入れ替えに対å¿?
540 * @og.rev 5.1.8.0 (2010/07/01) パã?ス方法ã?å†?ƒ¨実è£?¤‰更
541 * @og.rev 5.2.2.0 (2010/11/01) 条件付書式対å¿?
542 * @og.rev 5.4.2.0 (2011/12/01) ペã?ジブレイク、シートブレイク中でもã?ージエンドカãƒ?ƒˆが適用されるよã�?�«するã€?
543 * @og.rev 5.6.3.1 (2013/04/05) 条件付書式ã?属æ?終äº?–‡字対å¿?
544 *
545 * @param row
546 * @param bw
547 * @param sheetNameOrig
548 * @param sheetNameNew
549 * @throws IOException 書き込みに失敗したå?å�?
550 */
551 private void writeParsedRow( final String row, final BufferedWriter bw, final String sheetNameOrig, final String sheetNameNew ) throws IOException {
552 isPageEndCut = false;
553
554 String rowStr = new TagParser() {
555 @Override
556 protected void exec( final String str, final StringBuilder buf, final int offset ) {
557 String key = TagParser.checkKey( str, buf );
558
559 // 4.3.0.0 (2008/07/15) "<"がå?ってã�?�Ÿ場合には{@不整å�?エラー
560 if( key.indexOf( '<' ) >= 0 ){
561 queue.addMsg( "[ERROR]PARSE:{@と}の整合æ?が不正ですã?変数å†??特定ã?æ–?—å?に書式設定がされてã�?‚‹可能性がありますã?キー=" + key + HybsSystem.CR );
562 throw new HybsSystemException();
563 }
564
565 // QRコードã?処ç�??処ç�?¾Œã?offsetがé?ã‚?�Ÿめã?offsetをå?セãƒ?ƒˆ
566 if( key.startsWith( QRCODE_PREFIX ) ) {
567 setOffset( makeQRImage( row, offset, key.substring( QRCODE_PREFIX.length() ), buf ) );
568 }
569 // 画像置き換えã?処ç�??処ç�?¾Œã?offsetがé?ã‚?�Ÿめã?offsetをå?セãƒ?ƒˆ
570 else if( key.startsWith( IMG_PREFIX ) ) {
571 setOffset( changeImage( row, offset, key.substring( IMG_PREFIX.length() ), buf ) );
572 }
573 // コメンãƒ?アノテーション)による置き換えå?ç�??処ç�?¾Œã?offsetがé?ã‚?�Ÿめã?offsetをå?セãƒ?ƒˆ
574 else if( key.startsWith( ANNOTATION_PREFIX ) ) {
575 setOffset( parseByAnnotation( row, offset, key.substring( ANNOTATION_PREFIX.length() ), buf ) );
576 }
577 else {
578 String val = getValue( key );
579 // 5.5.2.4 (2012/05/16) String key は使われてã�?�ªã�??で、削除しますã?
580 // changeType( row, offset, key, val, getNativeType( key, val ), buf );
581 changeType( row, offset, val, getNativeType( key, val ), buf );
582 buf.append( val );
583 }
584
585 // 処ç�?¡Œがペã?ジエンドカãƒ?ƒˆの対象ã�?
586 if( queue.isFgcut() && PAGE_END_CUT.equals( key ) ) {
587 isPageEndCut = true;
588 }
589 }
590 }.doParse( row, VAR_START, VAR_END, false );
591
592 //==== ここからは後å?ç�?=========================================================
593 /*
594 * ペã?ジエンドカãƒ?ƒˆの判定ã?æœ?¾Œで処ç�?�™るã?
595 * {@PAGEENDCUT}が行ã?æœ??に書かれてã�?‚‹場合ã?、OVERFLOWになってã�?�ªã�?�¯能性ã�?
596 * あるため行ã?途中では判断できなã�?
597 */
598 // 5.4.2.0 (2011/12/01) シートブレイク中でもã?ージエンドカãƒ?ƒˆが適用されるよã�?�«するã€?
599 // (通常のペã?ジブレイクは先読み判定ã?ためペã?ジエンドカãƒ?ƒˆすると、ブレイク発生行è?身ã�?
600 // 削除されてしまã�?�Ÿめ現時点では未対å¿?
601 // if( isPageEndCut && status == OVERFLOW ) {
602 if( isPageEndCut && ( status == OVERFLOW || ( sheetBreakClm >= 0 && isPageBreak ) ) ) {
603 // ペã?ジエンドカãƒ?ƒˆの場合ã?ã€?�ž表示状態にするã€?
604 rowStr = rowStr.replace( ROW_START_TAG, ROW_START_TAG_INVISIBLE ) ;
605 }
606
607 /*
608 * オブジェクトで定義されてã�?‚‹ãƒ??ブル名を変更
609 */
610 if( rowStr.indexOf( OBJECT_SEARCH_STR ) >= 0 ) {
611 rowStr = rowStr.replace( OBJECT_SEARCH_STR + sheetNameOrig, OBJECT_SEARCH_STR + sheetNameNew );
612 }
613
614 /*
615 * 関数エラーを表示されなã�?�Ÿめã?ISERROR関数を埋め込み 4.2.3.1 (2008/06/19)
616 */
617 rowStr = replaceOoocError( rowStr );
618
619 /*
620 * グラフをシート毎にコピã? 5.1.8.0 (2010/07/01)
621 */
622 rowStr = replaceGraphInfo( rowStr, sheetNameOrig, sheetNameNew );
623
624 /*
625 * アノテーション(コメンãƒ?を削除 5.1.8.0 (2010/07/01)
626 * (コメントが存在すると起動が異常にé�?��なã‚?
627 */
628 if( rowStr.indexOf( ANNOTATION_START_TAG ) >= 0 ) {
629 rowStr = new TagParser() {}.doParse( rowStr, ANNOTATION_START_TAG, ANNOTATION_END_TAG );
630 }
631
632 /*
633 * 条件付書式対å¿?5.2.2.0 (2010/11/01)
634 * ãƒ??ブルå†?�«存在するスタイル名称を書き換ã�?
635 */
636 if( isNeedsReparse ) {
637 for( String name : repStyleList ) {
638 // if( rowStr.indexOf( TABLE_STYLE_NAME_START_TAG + name ) >= 0 ) {
639 // rowStr = rowStr.replace( TABLE_STYLE_NAME_START_TAG + name, TABLE_STYLE_NAME_START_TAG + name + "_" + sheetNameNew );
640 // }
641 // 5.6.3.1 (2013/04/05) 属æ?終äº?¿½åŠ?
642 if( rowStr.indexOf( TABLE_STYLE_NAME_START_TAG + name + TABLE_STYLE_NAME_END_TAG ) >= 0 ) {
643 rowStr = rowStr.replace( TABLE_STYLE_NAME_START_TAG + name + TABLE_STYLE_NAME_END_TAG, TABLE_STYLE_NAME_START_TAG + name + "_" + sheetNameNew + TABLE_STYLE_NAME_END_TAG );
644 }
645 }
646
647 }
648 //==============================================================================
649
650 bw.write( rowStr );
651 }
652
653 /**
654 * 帳票ãƒ??タに応じて、カラãƒ??属æ?を変更(æ–?—型⇒数値åž?に変更しますã?
655 *
656 * @og.rev 5.1.8.0 (2010/07/01) 新規作æ?
657 * @og.rev 5.5.2.4 (2012/05/16) String key は使われてã�?�ªã�??で、削除しますã?
658 *
659 * @param row
660 * @param curOffset
661 * @param val
662 * @param type
663 * @param sb
664 */
665 // private void changeType( final String row, final int curOffset, final String key
666 private void changeType( final String row, final int curOffset
667 , final String val, final NativeType type, final StringBuilder sb ) {
668 if( val == null || val.length() == 0 ) {
669 return;
670 }
671 // 書き換え対象は数値型ã?み
672 if( type != NativeType.INT && type != NativeType.LONG && type != NativeType.DOUBLE ) {
673 return;
674 }
675 // 処ç�?¯¾象がセルでなã�?オブジェクãƒ?は書き換えしなã�?
676 if( !isCell( row, curOffset ) ) {
677 return;
678 }
679
680 // セルのæ–?—が{@xxxx_n}のみであったå?合だけã?数値定義の判定を行うã€?
681 // (関数å†?�«{@xxxx_n}等があったå?合ã?、判定しなã�?<text:p>{@xxxx_n}</text:p>の場合ã?み))
682 if( sb.lastIndexOf( TEXT_START_TAG ) + TEXT_START_TAG.length() == sb.length()
683 && row.indexOf( TEXT_END_TAG, curOffset ) == curOffset ) {
684 int typeIdx = sb.lastIndexOf( TABLE_CELL_STRING_TYPE );
685 int cellIdx = sb.lastIndexOf( TABLE_CELL_START_TAG );
686 if( typeIdx >= 0 && cellIdx >= 0 && typeIdx > cellIdx ) {
687 // office:value-type="string" ã‚?office:value-type="float" office:value="xxx" に変換
688 sb.replace( typeIdx, typeIdx + TABLE_CELL_STRING_TYPE.length()
689 ,TABLE_CELL_FLOAT_TYPE + " " + TABLE_CELL_FLOAT_VAL_START + val + TABLE_CELL_FLOAT_VAL_END );
690 }
691 }
692 }
693
694 /**
695 * 引数にæŒ?®šされたæ–?—å?のNativeタイプを返しますã?
696 *
697 * リソース使用時ã?、各DBTypeで定義されたNativeタイプをã€?
698 * 未使用時ã?、å?からNativeタイプを取得して返しますã?
699 *
700 * @og.rev 5.1.8.0 (2010/07/01) NativeType#getType(String) のメソãƒ?ƒ‰を使用するように変更ã€?
701 *
702 * @param key
703 * @param val
704 *
705 * @return NATIVEの型ã?識別コーãƒ?
706 * @see org.opengion.fukurou.model.NativeType
707 */
708 private NativeType getNativeType( final String key, final String val ) {
709 if( val == null || val.length() == 0 ) {
710 return NativeType.STRING;
711 }
712
713 NativeType type = null;
714 if( queue.isFglocal() ) {
715 String name = key;
716 int conOffset = key.lastIndexOf( VAR_CON );
717 if( conOffset >= 0 ) {
718 int rownum = -1;
719 try {
720 rownum = Integer.valueOf( name.substring( conOffset + VAR_CON.length(), name.length() ) );
721 }
722 // '_'以降ã?æ–?—が数字でなã�??合ã?ã€?_'以降ã?æ–?—もカラãƒ?��のä¸?ƒ¨として扱ã�?
723 catch ( NumberFormatException ex ) {}
724 if( rownum >= 0 ) {
725 name = name.substring( 0, conOffset );
726 }
727 }
728 int col = queue.getBody().getColumnNo( name, false );
729 if( col >= 0 ) {
730 type = queue.getBody().getDBColumn( col ).getNativeType();
731 }
732 }
733
734 if( type == null ) {
735 // ,は削除した状態で判å®?
736 String repVal = val.replace( ",", "" );
737 // type = StringUtil.getNativeType( repVal );
738 type = NativeType.getType( repVal ); // 5.1.8.0 (2010/07/01) NativeType#getType(String) のメソãƒ?ƒ‰を使用
739 // 整数型でã€?nnnとなってã�?‚‹場合ã?、文字å?をして扱ã�?
740 if( type == NativeType.INT && repVal.length() >= 2 && repVal.charAt(0) == '0' ) {
741 type = NativeType.STRING;
742 }
743 }
744
745 return type;
746 }
747
748 /**
749 * コメンãƒ?アノテーションによる置き換えå?ç�?‚’行いまã�?
750 * こã?処ç�?�§は、offsetをé?めるため、戻りå?として処ç�?¾Œã?offsetを返しますã?
751 *
752 * @og.rev 5.1.8.0 (2010/07/01) 新規作æ?
753 *
754 * @param row
755 * @param curOffset
756 * @param key
757 * @param sb
758 *
759 * @return 処ç�?¾Œã?オフセãƒ?ƒˆ
760 */
761 private int parseByAnnotation( final String row, final int curOffset, final String key, final StringBuilder sb ) {
762 int offset = curOffset;
763 boolean isCell = isCell( row, offset );
764
765 // セルの場合ã?み置き換えã?判定を行う(オブジェクトã?場合ã?判定しなã�?
766 if( isCell ) {
767 int cellStrIdx = sb.lastIndexOf( TABLE_CELL_START_TAG, offset );
768 // office:value-type="float" office:value="xxx" ã‚?office:value-type="string" に変換
769 // 数値型ã?場合ã?、後で再度変換を行うã€?
770 // (æ–?—型に変換しておかなã�?�¨、å?がnullの場合でã‚?0"が表示されてしまã�?�Ÿã‚?
771 int floatIdx = sb.indexOf( TABLE_CELL_FLOAT_TYPE, cellStrIdx );
772 if( floatIdx >= 0 ) {
773 sb.replace( floatIdx, floatIdx + TABLE_CELL_FLOAT_TYPE.length(), TABLE_CELL_STRING_TYPE );
774
775 int floatStrIdx = sb.indexOf( TABLE_CELL_FLOAT_VAL_START, floatIdx );
776 if( floatStrIdx >= 0 ) {
777 int floatEndIdx = sb.indexOf( TABLE_CELL_FLOAT_VAL_END, floatStrIdx + TABLE_CELL_FLOAT_VAL_START.length() );
778 if( floatEndIdx >= 0 ) {
779 sb.replace( floatStrIdx, floatEndIdx + TABLE_CELL_FLOAT_VAL_END.length(), "" );
780 }
781 }
782 }
783 }
784
785 // アノテーションの値から、セルのæ–?—å?部åˆ?‚’置き換ã�?
786 int endIdx = isCell ? row.indexOf( TABLE_CELL_END_TAG, offset ) : row.indexOf( DRAW_END_KEY, offset );
787 if( endIdx >= 0 ) {
788 int textStrIdx = row.indexOf( TEXT_START_ANO_TAG, offset );
789 // セルのコメントã?場合ã?<text:pで検索すると、オブジェクトã?ãƒ?‚ストが検索されてã�?‚‹可能性があるã?
790 // こã?ため、セルの<text:pが見つかるまで検索を繰り返す
791 if( isCell ) {
792 while( !isCell( row, textStrIdx ) && textStrIdx >= 0 ) {
793 textStrIdx = row.indexOf( TEXT_START_ANO_TAG, textStrIdx + 1 );
794 }
795 }
796 if( textStrIdx >= 0 && textStrIdx < endIdx ) {
797 // セルのコメントã?場合ã?</text:p>で検索すると、オブジェクトã?ãƒ?‚ストが検索されてã�?‚‹可能性があるã?
798 // こã?ため、セルの</text:p>が見つかるまで検索を繰り返す
799 int textEndIdx = row.lastIndexOf( TEXT_END_TAG, endIdx );
800 if( isCell ) {
801 while( !isCell( row, textEndIdx ) && textEndIdx >= 0 ) {
802 textEndIdx = row.lastIndexOf( TEXT_END_TAG, textEndIdx - 1 );
803 }
804 }
805 if( textEndIdx >= 0 && textStrIdx < textEndIdx && textEndIdx < endIdx ) {
806 // <text:p xxxx> の xxxx> の部åˆ?style定義など)を書き込み
807 int textStyleEnd = row.indexOf( TEXT_START_END_ANO_TAG, textStrIdx + TEXT_START_ANO_TAG.length() ) + TEXT_START_END_ANO_TAG.length();
808 sb.append( row.substring( offset, textStyleEnd ) );
809
810 // <text:pの中身(spanタグなどを取り除ã�?�Ÿ状態ã?æ–?—å?
811 String textVal = TagParser.checkKey( row.substring( textStyleEnd, textEndIdx ), sb );
812 // 取得したテキストå?にタグæ–?—が含まれてã�?‚‹場合ã?、å?ç�?�—なã�?
813 // if( textVal.indexOf( "<" ) < 0 && textVal.indexOf( ">" ) < 0 ) {
814 if( textVal.indexOf( '<' ) < 0 && textVal.indexOf( '>' ) < 0 ) {
815 // <text:p xxxx>を書きå?ã�?
816 String val = getValue( key );
817 // 5.5.2.4 (2012/05/16) String key は使われてã�?�ªã�??で、削除しますã?
818 // changeType( row, textEndIdx, key, val, getNativeType( key, textVal ), sb );
819 changeType( row, textEndIdx, val, getNativeType( key, textVal ), sb );
820 sb.append( val );
821 }
822 offset = textEndIdx;
823 }
824 }
825 }
826
827 return offset;
828 }
829
830 /**
831 * 現在のオフセãƒ?ƒˆがセルかどã�?�‹を返しますã?
832 *
833 * trueの場合ã?セルをã?falseの場合ã?オブジェクトを意味しますã?
834 *
835 * セルとして判定されるための条件は以下ã?通りですã?
836 * 現在のoffsetを基準としてã€?
837 * â‘?‰�に<draw:(オブジェクトã?開å§?が見つからなã�?
838 * ②前に<table:table-cell(セルの始まã‚?ã�?draw:(オブジェクトã?始まã‚?より後方にある
839 * ③後に</draw:(オブジェクトã?終わã‚?が見つからなã�?
840 * ④後に</draw:(オブジェクトã?終わã‚?ã�?/table:table-cell>(セルの終わã‚?より後方にある
841 *
842 * @param row
843 * @param offset
844 *
845 * @return 現在のオフセãƒ?ƒˆがセルかどã�?�‹(falseの場合ã?オブジェクãƒ?
846 */
847 private boolean isCell( final String row, final int offset ) {
848 int drawStartOffset = row.lastIndexOf( DRAW_START_KEY, offset );
849 if( drawStartOffset < 0 ) {
850 return true;
851 }
852 else {
853 int cellStartOffset = row.lastIndexOf( TABLE_CELL_START_TAG, offset );
854 if( drawStartOffset < cellStartOffset ) {
855 return true;
856 }
857 else {
858 int drawEndOffset = row.indexOf( DRAW_END_KEY, offset );
859 if( drawEndOffset < 0 ) {
860 return true;
861 }
862 else {
863 int cellEndOffset = row.indexOf( TABLE_CELL_END_TAG, offset );
864 // 5.1.8.0 (2010/07/01) Avoid unnecessary if..then..else statements when returning a boolean
865 return ( cellEndOffset >= 0 && cellEndOffset < drawEndOffset );
866 // if( cellEndOffset >= 0 && cellEndOffset < drawEndOffset ) {
867 // return true;
868 // }
869 // else {
870 // return false;
871 // }
872 }
873 }
874 }
875 }
876
877 /**
878 * QRコードを作æ?しますã?
879 * こã?処ç�?�§は、offsetをé?めるため、戻りå?として処ç�?¾Œã?offsetを返しますã?
880 *
881 * @og.rev 4.3.1.1 (2008/08/23) mkdirs の戻りå?判å®?
882 * @og.rev 4.3.3.5 (2008/11/08) ↑ã?判定ã?存在チェãƒ?‚¯を行ってから処ç�?�™るã?ファイル名に処ç�?¡Œを付加
883 * @og.rev 5.3.1.0 (2011/01/01) OpenOffice3.2対å¿?追åŠ?�—た画像をmanifest.xmlに登録する
884 *
885 * @param row
886 * @param curOffset
887 * @param key
888 * @param sb
889 *
890 * @return 処ç�?¾Œã?オフセãƒ?ƒˆ
891 */
892 private int makeQRImage( final String row, final int curOffset, final String key, final StringBuilder sb ) {
893 int offset = curOffset;
894
895 // {@QRCODE.XXXX}から実際に画像ã?パスが書かれてã�?‚‹部åˆ?�¾でを書き込ã‚?
896 offset = row.indexOf( DRAW_IMG_START_TAG, offset ) + DRAW_IMG_START_TAG.length();
897 sb.append( row.substring( curOffset, offset ) );
898 // 画像ã?パスの終äº?‚¤ンãƒ?ƒƒクスを求めã‚?
899 offset = row.indexOf( DRAW_IMG_HREF_END, offset ) + DRAW_IMG_HREF_END.length();
900
901 // QRCODEの画像ファイル名を求め書き込ã‚?
902 // 4.3.3.5 (2008/11/08) ファイル名に処ç�?¡Œを付加
903 String fileName = IMG_DIR + '/' + key + "_" + currentBaseRow + QRCODE_FILETYPE;
904 sb.append( fileName ).append( DRAW_IMG_HREF_END );
905
906 // QRCODEに書き込ã‚??を求めã‚?
907 String value = getValue( key );
908
909 // QRCODEの作æ?
910 // 4.3.3.5 (2008/11/08) ファイル名に処ç�?¡Œを付加
911 String fileNameAbs =
912 new File( path ).getAbsolutePath() + File.separator + IMG_DIR + File.separator + key + "_" + currentBaseRow + QRCODE_FILETYPE;
913
914 // 画像リンクが無効となってã�?‚‹場合ã?、Picturesのフォルãƒ?�Œ作æ?されてã�?�ªã�?�¯能性があã‚?
915 // 4.3.1.1 (2008/08/23) mkdirs の戻りå?判å®?
916 // 4.3.3.5 (2008/11/08) 存在チェãƒ?‚¯追åŠ?
917 if( !new File( fileNameAbs ).getParentFile().exists() ) {
918 if( new File( fileNameAbs ).getParentFile().mkdirs() ) {
919 System.err.println( fileNameAbs + " の ãƒ?‚£レクトリ作æ?に失敗しましたã€? );
920 }
921 }
922
923 QrcodeImage qrImage = new QrcodeImage();
924 qrImage.init( value, fileNameAbs );
925 qrImage.saveImage();
926
927 // 5.3.1.0 (2011/01/01) OpenOffice3.2対å¿?追åŠ?�—た画像をmanifest.xmlに登録する
928 addObjs.put( fileName, QRCODE_FILETYPE.substring( 1 ) );
929
930 // 読み込みOffsetを返しまã�?
931 return offset;
932 }
933
934 /**
935 * DBTableModelに設定されたパスから画像データを取得し、å?部に取り込みまã�?
936 * こã?処ç�?�§は、offsetをé?めるため、戻りå?として処ç�?¾Œã?offsetを返しますã?
937 *
938 * @og.rev 4.3.3.5 (2008/11/08) 新規追åŠ?
939 * @og.rev 4.3.3.6 (2008/11/15) 画像パスが存在しなã�??合ã?、リンクタグ(draw:image)自体を削除
940 * @og.rev 5.3.1.0 (2011/01/01) OpenOffice3.2対å¿?追åŠ?�—た画像をmanifest.xmlに登録する
941 *
942 * @param row
943 * @param curOffset
944 * @param key
945 * @param sb
946 *
947 * @return 処ç�?¾Œã?オフセãƒ?ƒˆ
948 */
949 private int changeImage( final String row, final int curOffset, final String key, final StringBuilder sb ) {
950 int offset = curOffset;
951 File imgFile = null;
952
953 // 画像ファイルを読み込ã‚?ƒ‘スを求めã‚?
954 String value = getValue( key );
955
956 if( value != null && value.length() > 0 ) {
957 imgFile = new File( HybsSystem.url2dir( value ) );
958 }
959
960 // 画像ファイルのパスがå?ってã�?�¦、実際に画像が存在する場å�?
961 if( imgFile != null && imgFile.exists() ) {
962 // {@IMG.XXXX}から実際に画像ã?パスが書かれてã�?‚‹部åˆ?�¾でを書き込ã‚?
963 offset = row.indexOf( DRAW_IMG_START_TAG, offset ) + DRAW_IMG_START_TAG.length();
964 sb.append( row.substring( curOffset, offset ) );
965
966 // 画像ã?パスの終äº?‚¤ンãƒ?ƒƒクスを求めã‚?
967 offset = row.indexOf( DRAW_IMG_HREF_END, offset ) + DRAW_IMG_HREF_END.length();
968
969 String fileNameOut = IMG_DIR + '/' + imgFile.getName();
970 sb.append( fileNameOut ).append( DRAW_IMG_HREF_END );
971
972 String fileNameOutAbs =
973 new File( path ).getAbsolutePath() + File.separator + IMG_DIR + File.separator + imgFile.getName();
974 if( !new File( fileNameOutAbs ).getParentFile().exists() ) {
975 if( new File( fileNameOutAbs ).getParentFile().mkdirs() ) {
976 System.err.println( fileNameOutAbs + " の ãƒ?‚£レクトリ作æ?に失敗しましたã€? );
977 }
978 }
979 FileUtil.copy( imgFile, new File( fileNameOutAbs ) );
980
981 // 5.3.1.0 (2011/01/01) OpenOffice3.2対å¿?追åŠ?�—た画像をmanifest.xmlに登録する
982 addObjs.put( fileNameOut, getSuffix( imgFile.getName() ) );
983 }
984 // 画像パスが設定されてã�?�ªã�??又ã?画像が存在しなã�??å�?
985 else {
986 // {@IMG.XXXX}から見てã€?draw:image> ... </draw:image>までをスキãƒ??する
987 offset = row.indexOf( DRAW_IMG_START_TAG, offset );
988 sb.append( row.substring( curOffset, offset ) );
989
990 offset = row.indexOf( DRAW_IMG_END_TAG, offset ) + DRAW_IMG_END_TAG.length();
991 }
992
993 // 読み込みOffsetを返しまã�?
994 return offset;
995 }
996
997 /**
998 * 変換後ã?行データで定義されてã�?‚‹関数にISERROR関数を埋め込みますã?
999 *
1000 * これは、OOoの関数の動作として、不正な引数等が入力された場å�?null値など)にã€?
1001 * エラー:xxxと表示されてしまã�?�Ÿめã?これを防ぐために関数エラーのハンドリングを行いã€?
1002 * エラーの場合ã?、空白æ–?—を返すようにしますã?
1003 *
1004 * @og.rev 4.3.7.2 (2009/06/15) 開始文字が変更になったため対å¿?
1005 * @og.rev 5.0.2.0 (2009/11/01) 関数å†??"(quot)は、メタæ–?—に変換する
1006 * @og.rev 5.1.7.0 (2010/06/01) 関数の終わりが)出なã�??合にエラーとなるバグを修正
1007 * @og.rev 5.1.8.0 (2010/07/01) パã?ス方法ã?å†?ƒ¨実è£?¤‰更
1008 *
1009 * @param row
1010 *
1011 * @return 変換後ã?行データ
1012 */
1013 private String replaceOoocError( final String row ) {
1014 // 4.3.7.2 (2009/06/15) OOOC_FUNCTION_START3の条件判定追åŠ??どちらかåˆ?�‹らなã�??で変数で受けるã?
1015 final String functionStart;
1016 if( row.indexOf( OOOC_FUNCTION_START_3 ) >= 0 ) { functionStart = OOOC_FUNCTION_START_3; }
1017 else if( row.indexOf( OOOC_FUNCTION_START ) >= 0 ) { functionStart = OOOC_FUNCTION_START; }
1018 else { return row; }
1019
1020 String rowStr = new TagParser() {
1021 @Override
1022 protected boolean checkIgnore( final int strOffset, final int endOffset ) {
1023 // 5.1.7.0 (2010/06/01) 関数の終わりが)出なã�??合にエラーとなるバグを修正
1024 // 単なる行参照でもã?of:=で始まるがこã?場合ã?ã€?–¢数でなã�?�Ÿめ終わりが)でなã�?
1025 // こã?ためã€?が見つからなã�?�¾たã?、タグの終わã‚?>)がå?に見つかったå?合ã?、エラー関数ã‚?
1026 // 埋め込まなã�?‚ˆã�?�«するã€?
1027 int tmpOffset = row.indexOf( ">", strOffset + 1 );
1028 return ( endOffset >= 0 && endOffset < tmpOffset );
1029 }
1030
1031 @Override
1032 protected void exec( final String str, final StringBuilder buf, final int offset ) {
1033 String key = str.substring( functionStart.length(), str.length() - OOOC_FUNCTION_END.length() ) + ")";
1034 key = key.replace( "\"", """" ).replace( OOO_CR, "" );
1035 buf.append( functionStart + "IF(ISERROR(" + key + ");"";" + key + OOOC_FUNCTION_END );
1036 }
1037 }.doParse( row, functionStart, OOOC_FUNCTION_END );
1038
1039 return rowStr;
1040 }
1041
1042 /**
1043 * グラフ表示ãƒ??タ部åˆ?‚’更新しますã?
1044 *
1045 * @og.rev 5.1.8.0 (2010/07/01) 新規作æ?
1046 * @og.rev 5.3.1.0 (2011/01/01) OpenOffice3.2対å¿?追åŠ?�—た画像をmanifest.xmlに登録する
1047 *
1048 * @param row
1049 * @param sheetOrig
1050 * @param sheetNew
1051 *
1052 * @return 変換後ã?行データ
1053 */
1054 private String replaceGraphInfo( final String row, final String sheetOrig, final String sheetNew ) {
1055 if( row.indexOf( GRAPH_START_TAG ) < 0 || row.indexOf( GRAPH_UPDATE_RANGE_START ) < 0 ) { return row; }
1056
1057 // final List<String> addObjs = new ArrayList<String>();
1058 String rowStr = new TagParser() {
1059 @Override
1060 protected void exec( final String str, final StringBuilder buf, final int offset ) {
1061 // <draw:object ... /> の部åˆ?
1062 String graphTag = str;
1063
1064 if( graphTag.indexOf( GRAPH_UPDATE_RANGE_START ) >= 0 ) {
1065 String nameOrig = TagParser.getValueFromTag( graphTag, GRAPH_HREF_START, GRAPH_HREF_END );
1066 if( new File( path + nameOrig ).exists() ) {
1067 String nameNew = nameOrig + "_" + pages;
1068
1069 // グラフオブジェクトã?定義ファイルをコピã?(./Object X/* â‡?./Object X_n/*)
1070 FileUtil.copyDirectry( path + nameOrig, path + nameNew );
1071 graphTag = graphTag.replace( GRAPH_HREF_START + nameOrig, GRAPH_HREF_START + nameNew );
1072
1073 // グラフオブジェクトã?画像イメージをコピã?(./ObjectReplacements/Object X â‡?./ObjectReplacements/Object X_n)
1074 // ※実体ã?コピã?しなã�?リンクの参ç?を無効にしておくことで、次回起動時にグラフã?再描画が行われる)
1075 // FileUtil.copy( path + GRAPH_OBJREPL + File.separator + nameOrig, path + "ObjectReplacements" + File.separator + nameNew );
1076 graphTag = graphTag.replace( GRAPH_HREF_START + GRAPH_OBJREPL + "/" + nameOrig, GRAPH_HREF_START + GRAPH_OBJREPL + "/" + nameNew );
1077
1078 // OpenOffice3.2対å¿?追åŠ?�—た画像をmanifest.xmlに登録する
1079 // addObjs.add( nameNew );
1080 addObjs.put( nameNew, "graph" );
1081
1082 // グラフオブジェクトã?定義ファイルに記述されてã�?‚‹定義ファイルをパースしã?シート名と{@XXXX}を置き換ã�?
1083 parseGraphContent( path + nameNew + File.separator + "content.xml", sheetOrig, sheetNew );
1084
1085 // グラフã?参ç?ç¯?›²のシート名を置き換ã�?
1086 String range = TagParser.getValueFromTag( str, GRAPH_UPDATE_RANGE_START, GRAPH_UPDATE_RANGE_END );
1087 graphTag = graphTag.replace( GRAPH_UPDATE_RANGE_START + range, GRAPH_UPDATE_RANGE_START + range.replace( sheetOrig, sheetNew ) );
1088 }
1089 }
1090
1091 buf.append( graphTag );
1092 }
1093 }.doParse( row, GRAPH_START_TAG, GRAPH_END_TAG );
1094
1095 // 5.3.1.0 (2011/01/01) OpenOffice3.2対å¿?追åŠ?�—た画像をmanifest.xmlに登録する
1096 // if( addObjs.size() > 0 ) {
1097 // parseManifest( path + "META-INF" + File.separator + "manifest.xml", addObjs.toArray( new String[0] ) );
1098 // parseManifest( path + "META-INF" + File.separator + "manifest.xml", addObjs.toArray( new String[addObjs.size()] ) );
1099 // parseManifest( path + "META-INF" + File.separator + "manifest.xml", addObjs.toArray( new String[addObjs.size()] ) );
1100 // }
1101
1102 return rowStr;
1103 }
1104
1105 /**
1106 * グラフデータのcontent.xmlをパースしますã?
1107 *
1108 * @og.rev 5.1.8.0 (2010/07/01) 新規作æ?
1109 *
1110 * @param fileName
1111 * @param sheetOrig
1112 * @param sheetNew
1113 */
1114 private void parseGraphContent( final String fileName, final String sheetOrig, final String sheetNew ) {
1115 String graphContent = readOOoXml( fileName );
1116
1117 // シート名の置き換ã�?
1118 if( graphContent.indexOf( GRAPH_CONTENT_START ) >= 0 ) {
1119 graphContent = new TagParser() {
1120 @Override
1121 protected void exec( final String str, final StringBuilder buf, final int offset ) {
1122 buf.append( str.replace( sheetOrig, sheetNew ) );
1123 }
1124 }.doParse( graphContent, GRAPH_CONTENT_START, GRAPH_CONTENT_END );
1125 }
1126
1127 // {@XXXX}の置き換ã�?
1128 if( graphContent.indexOf( VAR_START ) >= 0 ) {
1129 graphContent = new TagParser() {
1130 @Override
1131 public void exec( final String str, final StringBuilder buf, final int offset ) {
1132 buf.append( getHeaderFooterValue( str ) );
1133 }
1134 }.doParse( graphContent, VAR_START, VAR_END, false );
1135 }
1136
1137 writeOOoXml( fileName, graphContent );
1138 }
1139
1140 // /**
1141 // * META-INF/manifest.xmlに、追åŠ?�—たグラフオブジェクトを登録しますã?
1142 // *
1143 // * @og.rev 5.1.8.0 (2010/07/01) 新規作æ?
1144 // *
1145 // * @param fileName
1146 // * @param obj
1147 // */
1148 // private void parseManifest( final String fileName, final String[] objs ) {
1149 // String[] conArr = TagParser.tag2Array( readOOoXml( fileName ), MANIFEST_START_TAG, MANIFEST_END_TAG );
1150 //
1151 // StringBuilder buf = new StringBuilder();
1152 // buf.append( conArr[0] );
1153 // for( int i=2; i<conArr.length; i++ ) {
1154 // buf.append( conArr[i] );
1155 // }
1156 // for( int i=0; i<objs.length; i++ ) {
1157 // buf.append( "<manifest:file-entry manifest:media-type=\"text/xml\" manifest:full-path=\"" + objs[i] + "/content.xml\"/>" );
1158 // buf.append( "<manifest:file-entry manifest:media-type=\"text/xml\" manifest:full-path=\"" + objs[i] + "/styles.xml\"/>" );
1159 // buf.append( "<manifest:file-entry manifest:media-type=\"text/xml\" manifest:full-path=\"" + objs[i] + "/meta.xml\"/>" );
1160 // buf.append( "<manifest:file-entry manifest:media-type=\"application/vnd.oasis.opendocument.chart\" manifest:full-path=\"" + objs[i] + "/\"/>" );
1161 // }
1162 // buf.append( conArr[1] );
1163 //
1164 // writeOOoXml( fileName, buf.toString() );
1165 // }
1166
1167 /**
1168 * æŒ?®šされたキーの値を返しますã?
1169 *
1170 * @og.rev 4.3.0.0 (2008/07/18) アンãƒ??スコアの処ç�?¤‰更
1171 * @og.rev 4.3.5.0 (2008/02/01) カラãƒ?��と行番号æ–?—ã?位置はæœ?¾Œから検索する 4.3.3.4 (2008/11/01) 修正åˆ?
1172 *
1173 * @param key
1174 *
1175 * @return 値
1176 */
1177 private String getValue( final String key ) {
1178 // int conOffset = key.indexOf( VAR_CON );
1179 int conOffset = key.lastIndexOf( VAR_CON );
1180
1181 String value = null;
1182
1183 if( conOffset < 0 ) {
1184 value = getHeaderFooterValue( key );
1185 }
1186 else {
1187 String name = key.substring( 0, conOffset );
1188 int rownum = -1;
1189 try {
1190 rownum = Integer.valueOf( key.substring( conOffset + VAR_CON.length(), key.length() ) ) + currentBaseRow;
1191 }
1192 catch ( NumberFormatException ex ) {
1193 // 4.3.0.0 (2008/07/18) エラーが起きてもなにもしなã�??
1194 // queue.addMsg( "[ERROR]雛形の変数定義が誤ってã�?�¾すã?カラãƒ?��=" + name + HybsSystem.CR );
1195 // throw new Exception( ex );
1196 }
1197
1198 // 4.3.0.0 (2008/07/18) アンãƒ??スコア後が数字に変換できなã�??合ã?ヘッãƒ?ƒ•ãƒ?‚¿として認è?
1199 if( rownum < 0 ){
1200 value = getHeaderFooterValue( key );
1201 }
1202 else{
1203 value = getBodyValue( name, rownum );
1204 }
1205 }
1206
1207 return checkValue( value );
1208 }
1209
1210 /**
1211 * æŒ?®šされたキーのヘッãƒ??、フãƒ?‚¿ー値を返しますã?
1212 *
1213 * @og.rev 4.3.6.0 (2009/04/01) レンãƒ?ƒ©ー適用されてã�?�ªã�?ƒ�グを修正
1214 * @og.rev 5.0.2.0 (2009/11/01) ローカルリソースフラグを使用しなã�??合ã?、リソース変換を行わなã�??
1215 * @og.rev 5.1.6.0 (2010/05/01) ペã?ジNO出力対å¿?
1216 *
1217 * @param key
1218 *
1219 * @return 値
1220 */
1221 private String getHeaderFooterValue( final String key ) {
1222 String value = "";
1223
1224 // 5.1.6.0 (2010/05/01) ペã?ジNO出力対å¿?
1225 if( PAGE_NO.equals( key ) ) {
1226 value = String.valueOf( pages + 1 );
1227 }
1228 // æœ?¾Œã?行かオーバã?フロー時ã?フッター
1229 else if( status >= LASTROW ) {
1230 if( queue.getFooter() != null ) {
1231 int clmno = queue.getFooter().getColumnNo( key, false );
1232 if( clmno >= 0 ) {
1233 value = queue.getFooter().getValue( 0, clmno );
1234 // 5.0.2.0 (2009/11/01) ローカルリソースフラグを使用しなã�??合ã?、リソース変換を行わなã�??
1235 if( queue.isFglocal() ) {
1236 // 4.3.6.0 (2009/04/01)
1237 value = queue.getFooter().getDBColumn( clmno ).getRendererValue( value );
1238 }
1239 }
1240 }
1241 }
1242 // æœ?¾Œã?行にきてã�?�ªã�??合ã?ヘッãƒ??
1243 else {
1244 if( queue.getHeader() != null ) {
1245 int clmno = queue.getHeader().getColumnNo( key, false );
1246 if( clmno >= 0 ) {
1247 value = queue.getHeader().getValue( 0, clmno );
1248 // 5.0.2.0 (2009/11/01) ローカルリソースフラグを使用しなã�??合ã?、リソース変換を行わなã�??
1249 if( queue.isFglocal() ) {
1250 // 4.3.6.0 (2009/04/01)
1251 value = queue.getHeader().getDBColumn( clmno ).getRendererValue( value );
1252 }
1253 }
1254 }
1255 }
1256
1257 return value;
1258 }
1259
1260 /**
1261 * æŒ?®šされた行番号、キーのボディー値を返しますã?
1262 *
1263 * @og.rev 4.3.6.0 (2009/04/01) レンãƒ?ƒ©ー適用されてã�?�ªã�?ƒ�グを修正
1264 * @og.rev 4.3.6.2 (2009/04/15) 行番号のより小さã�?‚«ラãƒ?®š義を読んだ際に、å?部カウンタがクリアされてしまã�?ƒ�グを修正
1265 * @og.rev 4.3.6.2 (2009/04/15) ä¸?º¦オーバã?フローした場合に移行が全て空æ–?—で返ってしまã�?ƒ�グを修正
1266 * @og.rev 5.0.2.0 (2009/11/01) ローカルリソースフラグを使用しなã�??合ã?、リソース変換を行わなã�??
1267 * @og.rev 5.1.6.0 (2010/05/01) 行番号出力対å¿?
1268 * @og.rev 5.1.7.0 (2010/06/01) è¤?•°シート対å¿?
1269 * @og.rev 5.1.9.0 (2010/08/01) æœ?µ‚行で正しくシートブレイクされなã�?ƒ�グを修正
1270 *
1271 * @param key
1272 * @param rownum
1273 *
1274 * @return 値
1275 */
1276 private String getBodyValue( final String key, final int rownum ) {
1277 // if( status == OVERFLOW || isPageBreak ) { return ""; }
1278 if( isPageBreak ) { return ""; } // 4.3.6.2 (2009/04/15) OVERFLOW時バグ修正
1279
1280 int clmno = queue.getBody().getColumnNo( key, false );
1281 if( clmno < 0 && !ROW_NO.equals( key ) ) { return ""; }
1282
1283 // ペã?ジブレイク判定ã?先読みして判断
1284 if( PAGE_BREAK.equals( key ) ) {
1285 // if( rownum <= queue.getBody().getRowCount() - 2 ) {
1286 if( rownum < queue.getBody().getRowCount() - 1 ) {
1287 if( !( queue.getBody().getValue( rownum, clmno ).equals( queue.getBody().getValue( rownum + 1, clmno ) ) ) ) {
1288 isPageBreak = true;
1289 }
1290 }
1291 return "";
1292 }
1293
1294 // 5.1.7.0 (2010/06/01) è¤?•°シート対å¿?
1295 // シートブレイクは後読みして判断(前ã?行と異なってã�?�Ÿ場合にブレイク)
1296 if( sheetBreakClm >= 0 ) {
1297 // 5.1.9.0 (2010/08/01) æœ?µ‚行で正しくシートブレイクされなã�?ƒ�グを修正
1298 // if( rownum < queue.getBody().getRowCount() - 1 && currentBaseRow != rownum ) {
1299 if( rownum < queue.getBody().getRowCount() && currentBaseRow != rownum ) {
1300 if( !( queue.getBody().getValue( currentBaseRow, sheetBreakClm ).equals( queue.getBody().getValue( rownum, sheetBreakClm ) ) ) ) {
1301 isPageBreak = true;
1302 return "";
1303 }
1304 }
1305 }
1306
1307 if( rownum >= queue.getBody().getRowCount() ) {
1308 status = OVERFLOW;
1309 return "";
1310 }
1311
1312 if( rownum == queue.getBody().getRowCount() - 1 ) {
1313 // status = LASTROW;
1314 status = Math.max( LASTROW, status ); // 4.3.6.2 (2009/04/15) 自身のスãƒ??タスと比べて大きい方を返す
1315 }
1316
1317 String value = null;
1318 // 5.1.6.0 (2010/05/01) ペã?ジNO出力対å¿?
1319 if( ROW_NO.equals( key ) ) {
1320 value = String.valueOf( rownum + 1 );
1321 }
1322 else {
1323 value = queue.getBody().getValue( rownum, clmno );
1324 // 5.0.2.0 (2009/11/01) ローカルリソースフラグを使用しなã�??合ã?、リソース変換を行わなã�??
1325 if( queue.isFglocal() ) {
1326 // 4.3.6.0 (2009/04/01)
1327 value = queue.getBody().getDBColumn( clmno ).getRendererValue( value );
1328 }
1329 }
1330
1331 // 4.3.6.2 (2009/04/15)
1332 if( currentMaxRow < rownum + 1 ) {
1333 currentMaxRow = rownum + 1;
1334 }
1335
1336 return value;
1337 }
1338
1339 /**
1340 * 値に'<'ã‚?>','&'が含まれてã�?�Ÿ場合にメタæ–?—に変換しますã?
1341 *
1342 * @og.rev 5.0.2.0 (2009/11/01) 改行Cの変換ロジãƒ?‚¯を追åŠ?
1343 * @og.rev 5.0.2.0 (2009/11/01) リソース変換時ã?spanタグを除去
1344 *
1345 * @param value
1346 *
1347 * @return 変換後ã?値
1348 */
1349 private String checkValue( final String value ) {
1350 String rtn = value;
1351
1352 // 5.0.2.0 (2009/11/01)
1353 if( queue.isFglocal() ) {
1354 int idx = -1;
1355 if( ( idx = rtn.indexOf( "<span" ) ) >= 0 ) {
1356 String spanStart = rtn.substring( idx, rtn.indexOf( '>', idx ) + 1 );
1357 rtn = rtn.replace( spanStart, "" ).replace( "</span>", "" );
1358 }
1359 }
1360
1361 if( rtn.indexOf( '&' ) >= 0 ) {
1362 rtn = rtn.replace( "&", "&" );
1363 }
1364 if( rtn.indexOf( '<' ) >= 0 ) {
1365 rtn = rtn.replace( "<", "<" );
1366 }
1367 if( rtn.indexOf( '>' ) >= 0 ) {
1368 rtn = rtn.replace( ">", ">" );
1369 }
1370 if( rtn.indexOf( '\n' ) >= 0 ) {
1371 rtn = rtn.replace( "\r\n", "\n" ).replace( "\n", OOO_CR );
1372 }
1373
1374 return rtn;
1375 }
1376
1377 /**
1378 * 引数のæ–?—å?を指定された開始タグ、終äº?‚¿グで解析し配å?として返しますã?
1379 * 開始タグより前ã?æ–?—å?は0番目に、終äº?‚¿グより後ã?æ–?—å?は1番目に格納されますã?
1380 * 2番目以降にã€?–‹始タグ、終äº?‚¿グの部åˆ?�Œ格納されますã?
1381 *
1382 * @param str
1383 * @param startTag
1384 * @param endTag
1385 *
1386 * @return 解析結果の配å?
1387 */
1388 private static String[] tag2Array( final String str, final String startTag, final String endTag ) {
1389 String header = null;
1390 String footer = null;
1391 List<String> body = new ArrayList<String>();
1392
1393 int preOffset = -1;
1394 int curOffset = 0;
1395
1396 while( true ) {
1397 curOffset = str.indexOf( startTag, preOffset + 1 );
1398 if( curOffset < 0 ) {
1399 curOffset = str.lastIndexOf( endTag ) + endTag.length();
1400 body.add( str.substring( preOffset, curOffset ) );
1401
1402 footer = str.substring( curOffset );
1403 break;
1404 }
1405 else if( preOffset == -1 ) {
1406 header = str.substring( 0, curOffset );
1407 }
1408 else {
1409 body.add( str.substring( preOffset, curOffset ) );
1410 }
1411 preOffset = curOffset;
1412 }
1413
1414 String[] arr = new String[body.size()+2];
1415 arr[0] = header;
1416 arr[1] = footer;
1417 for( int i=0; i<body.size(); i++ ) {
1418 arr[i+2] = body.get(i);
1419 }
1420
1421 return arr;
1422 }
1423
1424 /**
1425 * 帳票処ç�?‚ューをå?に、style.xml(ヘッãƒ??、フãƒ?‚¿ー)を書き換えますã?
1426 *
1427 * @og.rev 5.1.8.0 (2010/07/01) パã?ス方法ã?å†?ƒ¨実è£?¤‰更
1428 */
1429 private void execStyles() {
1430 String fileName = path + "styles.xml";
1431 String content = readOOoXml( fileName );
1432
1433 if( content.indexOf( VAR_START ) < 0 ) { return; }
1434 content = new TagParser() {
1435 @Override
1436 public void exec( final String str, final StringBuilder buf, final int offset ) {
1437 buf.append( getHeaderFooterValue( str ) );
1438 }
1439 }.doParse( readOOoXml( fileName ), VAR_START, VAR_END, false );
1440
1441 writeOOoXml( fileName, content );
1442 }
1443
1444 /**
1445 * 帳票処ç�?‚ューをå?に、meta.xmlを書き換えますã?
1446 *
1447 * @og.rev 5.1.6.0 (2010/05/01) 画面帳票作æ?機è?対å¿?API経由では出力されなã�?�“とがあã‚?
1448 */
1449 private void execMeta() {
1450 String fileName = path + "meta.xml";
1451
1452 String meta = readOOoXml( fileName );
1453
1454 // シート数書き換ã�?
1455 // 5.1.6.0 (2010/05/01)
1456 if( meta.indexOf( TABLE_COUNT_START_TAG ) >=0 ){
1457 String tableCount = TagParser.getValueFromTag( meta, TABLE_COUNT_START_TAG, TABLE_COUNT_END_TAG );
1458 // meta = meta.replace( TABLE_COUNT_START_TAG + tableCount, TABLE_COUNT_START_TAG + String.valueOf( pages ) );
1459 meta = meta.replace( TABLE_COUNT_START_TAG + tableCount, TABLE_COUNT_START_TAG + pages );
1460 }
1461
1462 // セル数書き換ã�?
1463 // 5.1.6.0 (2010/05/01)
1464 if( meta.indexOf( CELL_COUNT_START_TAG ) >=0 ){
1465 String cellCount = TagParser.getValueFromTag( meta, CELL_COUNT_START_TAG, CELL_COUNT_END_TAG );
1466 // meta = meta.replace( CELL_COUNT_START_TAG + cellCount, CELL_COUNT_START_TAG + String.valueOf( Integer.parseInt( cellCount ) * pages ) );
1467 meta = meta.replace( CELL_COUNT_START_TAG + cellCount, CELL_COUNT_START_TAG + ( Integer.parseInt( cellCount ) * pages ) );
1468 }
1469
1470 // オブジェクト数書き換ã�?
1471 // 5.1.6.0 (2010/05/01)
1472 if( meta.indexOf( OBJECT_COUNT_START_TAG ) >= 0 ){
1473 String objectCount = TagParser.getValueFromTag( meta, OBJECT_COUNT_START_TAG, OBJECT_COUNT_END_TAG );
1474 //4.2.4.0 (2008/06/02) 存在しなã�??合ã?nullで帰ってくるので無視すã‚?
1475 if( objectCount != null){
1476 // meta = meta.replace( OBJECT_COUNT_START_TAG + objectCount, OBJECT_COUNT_START_TAG + String.valueOf( Integer.parseInt( objectCount ) * pages ) );
1477 meta = meta.replace( OBJECT_COUNT_START_TAG + objectCount, OBJECT_COUNT_START_TAG + ( Integer.parseInt( objectCount ) * pages ) );
1478 }
1479 }
1480
1481 writeOOoXml( fileName, meta );
1482 }
1483
1484 /**
1485 * 書き換え対象のスタイルリストを取得しますã?
1486 *
1487 * @og.rev 5.2.2.0 (2010/11/01) 条件付書式対å¿?
1488 *
1489 * @param header content.xmlのヘッãƒ??
1490 */
1491 private void getRepStyleList( final String header ) {
1492 String[] tags = tag2Array( header, STYLE_START_TAG, STYLE_END_TAG );
1493 Set<String> origNameSet = pageNameMap.keySet();
1494 for( int i=2; i<tags.length; i++ ) {
1495 for( String origName : origNameSet ) {
1496 if( tags[i].indexOf( "=\"" + origName + "." ) >= 0 ) {
1497 String styleName = TagParser.getValueFromTag( tags[i], STYLE_NAME_START_TAG, STYLE_NAME_END_TAG );
1498 repStyleList.add( styleName );
1499 break;
1500 }
1501 }
1502 }
1503 }
1504
1505 /**
1506 * 帳票処ç�?‚ューをå?に、content.xmlを書き換えますã?
1507 * まずã?XMLをä¸?—¦メモリ上に展開した後ã?シート単位にåˆ?§£しã?ãƒ??タの埋め込みを行いますã?
1508 *
1509 * @og.rev 5.2.2.0 (2010/11/01) 条件付書式対å¿?
1510 */
1511 private void execContentHeader() {
1512 String fileName = path + "content.xml";
1513 String content = readOOoXml( fileName );
1514
1515 // ファイルの解析し、シーãƒ?行単位にåˆ?§£
1516 String[] tags = tag2Array( content, STYLE_START_TAG, STYLE_END_TAG );
1517 String header = tags[0];
1518 String footer = tags[1];
1519
1520 BufferedWriter bw = null;
1521 try {
1522 bw = getWriter( fileName );
1523 bw.write( xmlHeader );
1524 bw.write( '\n' );
1525 bw.write( header );
1526
1527 // スタイルæƒ??にシート依存ã?æƒ??があるå?合ã?、ã?ージåˆ?� けコピã?するã€?
1528 Set<String> origNameSet = pageNameMap.keySet();
1529 for( int i=2; i<tags.length; i++ ) {
1530 boolean isReplace = false;
1531 for( String origName : origNameSet ) {
1532 if( tags[i].indexOf( "=\"" + origName + "." ) >= 0 ) {
1533 List<String> newNames = pageNameMap.get( origName );
1534 for( String newName : newNames ) {
1535 String styleStr = tags[i].replace( "=\"" + origName + "." , "=\"" + newName + "." );
1536 // シート名の書き換ã�?
1537 String styleName = TagParser.getValueFromTag( styleStr, STYLE_NAME_START_TAG, STYLE_NAME_END_TAG );
1538 styleStr = styleStr.replace( STYLE_NAME_START_TAG + styleName, STYLE_NAME_START_TAG + styleName + "_" + newName );
1539 bw.write( styleStr );
1540 isReplace = true;
1541 }
1542 break;
1543 }
1544 }
1545
1546 if( !isReplace ) {
1547 bw.write( tags[i] );
1548 }
1549 }
1550
1551 bw.write( footer );
1552 bw.flush();
1553 }
1554 catch ( IOException ex ) {
1555 queue.addMsg( "[ERROR]PARSE:error occurer while write ReParsed Sheet " + fileName + HybsSystem.CR );
1556 throw new HybsSystemException( ex );
1557 }
1558 finally {
1559 Closer.ioClose( bw );
1560 }
1561 }
1562
1563 /**
1564 * content.xmlのヘッãƒ??部åˆ?‚’出力したcontent.xmlに、ã?ãƒ?ƒ€ー部åˆ?»¥降を出力しã�?
1565 * content.xml.bakをã?ージしますã?
1566 *
1567 * @og.rev 5.2.2.0 (2010/11/01) 条件付書式対å¿?
1568 */
1569 private void execMergeContent() {
1570 FileChannel srcChannel = null;
1571 FileChannel destChannel = null;
1572 try {
1573 srcChannel = new FileInputStream( path + "content.xml.tmp" ).getChannel();
1574 destChannel = new FileOutputStream( path + "content.xml", true ).getChannel();
1575 srcChannel.transferTo(0, srcChannel.size(), destChannel);
1576 }
1577 catch ( IOException ex ) {
1578 queue.addMsg( "[ERROR]PARSE:error occurer while merge content.xml" + HybsSystem.CR );
1579 throw new HybsSystemException( ex );
1580 }
1581 finally {
1582 Closer.ioClose( srcChannel );
1583 Closer.ioClose( destChannel );
1584 }
1585 FileUtil.deleteFiles( new File( path + "content.xml.tmp" ) );
1586 }
1587
1588 /**
1589 * META-INF/manifest.xmlに、追åŠ?�—たオブジェクãƒ?グラフã?画åƒ?を登録しますã?
1590 *
1591 * @og.rev 5.3.1.0 (2011/12/01) 新規作æ?
1592 */
1593 private void execManifest() {
1594 String fileName = path + "META-INF" + File.separator + "manifest.xml";
1595 String[] conArr = TagParser.tag2Array( readOOoXml( fileName ), MANIFEST_START_TAG, MANIFEST_END_TAG );
1596
1597 StringBuilder buf = new StringBuilder();
1598 buf.append( conArr[0] );
1599 for( int i=2; i<conArr.length; i++ ) {
1600 buf.append( conArr[i] );
1601 }
1602 for( Map.Entry<String,String> entry : addObjs.entrySet() ) {
1603 if( "graph".equals( entry.getValue() ) ) {
1604 buf.append( "<manifest:file-entry manifest:media-type=\"text/xml\" manifest:full-path=\"" + entry.getKey() + "/content.xml\"/>" );
1605 buf.append( "<manifest:file-entry manifest:media-type=\"text/xml\" manifest:full-path=\"" + entry.getKey() + "/styles.xml\"/>" );
1606 buf.append( "<manifest:file-entry manifest:media-type=\"text/xml\" manifest:full-path=\"" + entry.getKey() + "/meta.xml\"/>" );
1607 buf.append( "<manifest:file-entry manifest:media-type=\"application/vnd.oasis.opendocument.chart\" manifest:full-path=\"" + entry.getKey() + "/\"/>" );
1608 }
1609 else {
1610 buf.append( "<manifest:file-entry manifest:media-type=\"image/" + entry.getValue() + "\" manifest:full-path=\"" + entry.getKey() + "\"/>" );
1611 }
1612 }
1613 buf.append( conArr[1] );
1614
1615 writeOOoXml( fileName, buf.toString() );
1616 }
1617
1618 /**
1619 * XMLファイルを読み取り、結果を返しますã?
1620 * OOoのXMLファイルは全て1行めがxml宣è¨?�§ã€?行目がå?容全体とã�?�†形式であるためã€?
1621 * ここではã€?行目のå†?®¹部åˆ?‚’返しますã?
1622 *
1623 * @og.rev 4.3.6.0 (2009/04/01) meta.xmlでコンãƒ?ƒ³ãƒ??部åˆ?�Œ改行されてã�?‚‹場合があるため、ループを回して読込み
1624 *
1625 * @param fileName
1626 *
1627 * @return 読み取った文字å?
1628 */
1629 private String readOOoXml( final String fileName ) {
1630 File file = new File ( fileName );
1631
1632 BufferedReader br = null;
1633 String tmp = null;
1634 StringBuilder buf = new StringBuilder();
1635 try {
1636 br = new BufferedReader( new InputStreamReader( new FileInputStream( file ), "UTF-8" ) );
1637 xmlHeader = br.readLine();
1638 // str = br.readLine();
1639 while( ( tmp = br.readLine() ) != null ) { // 4.3.6.0 (2009/04/01)
1640 buf.append( tmp );
1641 }
1642 }
1643 catch( IOException ex ) {
1644 queue.addMsg( "[ERROR]PARSE:Failed to read " + fileName + HybsSystem.CR );
1645 throw new HybsSystemException( ex );
1646 }
1647 finally {
1648 Closer.ioClose( br );
1649 }
1650
1651 String str = buf.toString();
1652 if( xmlHeader == null || xmlHeader.length() == 0 || str == null || str.length() == 0 ) {
1653 queue.addMsg( "[ERROR]PARSE:Maybe " + fileName + " is Broken!" + HybsSystem.CR );
1654 throw new HybsSystemException();
1655 }
1656
1657 return str;
1658 }
1659
1660 /**
1661 * XMLファイルを書き込みますã?
1662 * OOoのXMLファイルは全て1行めがxml宣è¨?�§ã€?行目がå?容全体とã�?�†形式であるためã€?
1663 * ここではã€?行目のå†?®¹部åˆ?‚’渡すことで、XMLファイルを作æ?しますã?
1664 *
1665 * @param fileName 書き込ã‚?MLファイルå�?
1666 * @param str 書き込ã‚?–‡字å?
1667 */
1668 private void writeOOoXml( final String fileName, final String str ) {
1669 BufferedWriter bw = null;
1670 try {
1671 bw = getWriter( fileName );
1672 bw.write( xmlHeader );
1673 bw.write( '\n' );
1674 bw.write( str );
1675 bw.flush();
1676 }
1677 catch( IOException ex ) {
1678 queue.addMsg( "[ERROR]PARSE:Failed to write " + fileName + HybsSystem.CR );
1679 throw new HybsSystemException( ex );
1680 }
1681 finally {
1682 Closer.ioClose( bw );
1683 }
1684 }
1685
1686 /**
1687 * XMLファイル書き込み用のライターを返しますã?
1688 *
1689 * @param fileName ファイルå�?
1690 *
1691 * @return ライター
1692 */
1693 private BufferedWriter getWriter( final String fileName ) {
1694 return getWriter( fileName, false );
1695 }
1696
1697 /**
1698 * XMLファイル書き込み用のライターを返しますã?
1699 *
1700 * @param fileName ファイルå�?
1701 * @param append アベンドするか
1702 *
1703 * @return ライター
1704 */
1705 private BufferedWriter getWriter( final String fileName, final boolean append ) {
1706 File file = new File ( fileName );
1707 BufferedWriter bw;
1708 try {
1709 bw = new BufferedWriter( new OutputStreamWriter( new FileOutputStream( file, append ), "UTF-8" ) );
1710 }
1711 catch ( UnsupportedEncodingException ex ) {
1712 queue.addMsg( "[ERROR] Input File is written by Unsupported Encoding" );
1713 throw new HybsSystemException( ex );
1714 }
1715 catch ( FileNotFoundException ex ) {
1716 queue.addMsg( "[ERROR] File not Found" );
1717 throw new HybsSystemException( ex );
1718 }
1719 return bw;
1720 }
1721
1722 /**
1723 * ファイル名から拡張å?小文å?を求めますã?
1724 *
1725 * @param fileName 拡張子を取得する為のファイルå�?
1726 *
1727 * @return 拡張å?小文å?
1728 */
1729 public static String getSuffix( final String fileName ) {
1730 String suffix = null;
1731 if( fileName != null ) {
1732 int sufIdx = fileName.lastIndexOf( '.' );
1733 if( sufIdx >= 0 ) {
1734 suffix = fileName.substring( sufIdx + 1 ).toLowerCase( Locale.JAPAN );
1735 }
1736 }
1737 return suffix;
1738 }
1739 }
1740