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