OSDN Git Service

#34479 対応中
[jaxcel/jaxcel.git] / Jaxcel / src / org / hanei / jaxcel / parser / IfParser.java
1 /**
2  * Copyright 2014 Hanei Management Co.,Ltd. 
3  * 
4  * This file is part of Jaxcel
5  * 
6  *  Jaxcel is free software: you can redistribute it and/or modify
7  *  it under the terms of the GNU Lesser General Public License as published by
8  *  the Free Software Foundation, either version 3 of the License, or
9  *  (at your option) any later version.
10  *
11  *  Jaxcel is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU Lesser General Public License for more details.
15  *
16  *  You should have received a copy of the GNU Lesser General Public License
17  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
18  */
19 package org.hanei.jaxcel.parser;
20
21 import java.util.Map;
22 import org.apache.commons.lang3.BooleanUtils;
23 import org.apache.commons.lang3.math.NumberUtils;
24 import org.apache.poi.ss.usermodel.Cell;
25 import org.apache.poi.ss.usermodel.Sheet;
26 import org.apache.poi.ss.util.CellRangeAddress;
27 import org.hanei.jaxcel.report.ELManager;
28 import org.hanei.jaxcel.report.JaxcelContext;
29 import org.hanei.jaxcel.util.ExcelUtil;
30
31 /**
32  * if句のパーサー実装<br>
33  * 
34  * <h4>テンプレートの書式</h4>
35  * <h5>#if(${expression}[ rows:"number"][ cols:"number"][ delete:"left|up|clear"][ block:"true|false"])</h5>
36  * <p>if句。expression判定式がtrue判定の場合は指定範囲の出力、false判定の場合は指定の方法で範囲を削除する。</p>
37  * <table border="1" cellspacing="1">
38  * <tr><th>属性</th><th>説明</th></tr>
39  * <tr>
40  *              <td>${expression}</td>
41  *              <td>判定式。"${" 式 "}" のフォーマットで指定する。Bool値を返す式を指定する。Bool値を返さない式の場合は、値がnullでなければtrueと判断する。</td>
42  * </tr>
43  * <tr>
44  *              <td>rows</td>
45  *              <td>制御範囲の行数を正の整数で指定する。"1"指定で#if指示子が記述された行のみとなる。省略すると規定値である "1"となる。</td>
46  * </tr>
47  * <tr>
48  *              <td>cols</td>
49  *              <td>制御範囲の列数を正の整数で指定する。"1"指定で#if指示子が記述された列のみとなる。省略すると規定値である "1"となる。</td>
50  * </tr>
51  * <tr>
52  *              <td>delete</td>
53  *              <td>判定式がflse判定の場合の制御範囲に対する操作を指定する。省略すると規定値である"left"となる。<br>
54  *              <table>
55  *              <tr><td>left</td><td>制御範囲セルを削除し、左に詰める。</td></tr>
56  *              <tr><td>up</td><td>制御範囲セルを削除し、上に詰める。</td></tr>
57  *              <tr><td>clear</td><td>制御範囲セルの値・計算式をクリアするのみで詰めない。</td></tr>
58  *              </table>
59  * </tr>
60  * <tr>
61  *              <td>block</td>
62  *              <td>矩形範囲での制御を行うかについて指定する。省略すると規定値である"true"となる。<br>
63  *              <table>
64  *              <tr><td>true</td><td>制御範囲を矩形範囲(rows・colsオプションで指定する範囲)とする。</td></tr>
65  *              <tr><td>false</td><td>制御範囲を矩形範囲に含まれる行・列全体とする。<br>
66  *              deleteオプションが"left"の場合、矩形範囲に含まれる列全体が制御範囲となる。<br>
67  *              deleteオプションが"up"の場合、矩形範囲に含まれる行全体が制御範囲となる。<br>
68  *              deleteオプションが"clear"の場合は無効。</td></tr>
69  *              </table></td>
70  * </tr>
71  * </table>
72  * 
73  * @since 1.01.00
74  * @author Noboru Saito
75  */
76 public class IfParser extends AbstractTLParser {
77
78         private static final String LEFT = "left";
79         private static final String UP = "up";
80         private static final String CLEAR = "clear";
81         private static final String ROWS = "rows";
82         private static final String COLS = "cols";
83         private static final String DELETE = "delete";
84         private static final String BLOCK = "block";
85         private static final String ROW = "row";
86         private static final String COL = "col";
87         private static final int SPAN_DEF = 1;
88
89         @Override
90         public void parse(JaxcelContext context) {
91                 log.trace("parse start");
92
93                 Sheet sheet = context.getCurrentSheet();
94                 Cell cell = context.getCurrentCell();
95                 ELManager elMgr = context.getElManager();
96                 Map<String, Object> attributeMap = context.getAttributeMap();
97                 String expression = null;
98                 String delete = null;
99                 boolean block = true;
100                 int rowSpan = SPAN_DEF;         // row
101                 int colSpan = SPAN_DEF;         // column
102
103                 // セルタイプのチェック、指示子をクリア
104                 switch(cell.getCellType()) {
105                 case Cell.CELL_TYPE_STRING:
106                         cell.setCellValue(ExcelUtil.replaceFirstCellValue(cell, context.getTemplateString(), ""));
107                         break;
108                 default:
109                         // セルタイプが文字列でない場合パース終了
110                         log.error("cell type is not strng");
111                         log.trace("parse end");
112                         return;
113                 }
114
115                 // EL式
116                 if(attributeMap.containsKey(Constants.EXPRESSION)) {
117                         expression = (String) attributeMap.get(Constants.EXPRESSION);
118                         log.debug("expression: {}", expression);
119                 }
120                 else {
121                         // EL式が存在しな場合は終了
122                         log.error("expression is null");
123                         log.trace("parse end");
124                         return;
125                 }
126                 
127                 // blick:"true|false"  foreachレンジをブロック範囲で繰り返すかの指定 デフォルト true
128                 if(attributeMap.containsKey(BLOCK)) {
129                         block = BooleanUtils.toBoolean((String) attributeMap.get(BLOCK));
130                 }
131                 // delete:"left|up|clear"  判定式がflse判定の場合の制御範囲に対する操作を指定 デフォルト left
132                 if(attributeMap.containsKey(DELETE)) {
133                         delete = (String) attributeMap.get(DELETE);
134                 }
135                 // rows:"number"  範囲 デフォルト 1
136                 if(attributeMap.containsKey(ROWS)) {
137                         rowSpan = NumberUtils.toInt((String) attributeMap.get(ROWS));
138                         if(rowSpan <= 0) {
139                                 log.warn("{} is illegal argument. set default: {}", ROWS, SPAN_DEF);
140                                 rowSpan = SPAN_DEF;
141                         }
142                 }
143                 // cols:"number"  範囲 デフォルト 1
144                 if(attributeMap.containsKey(COLS)) {
145                         colSpan = NumberUtils.toInt((String) attributeMap.get(COLS));
146                         if(colSpan <= 0) {
147                                 log.warn("{} is illegal argument. set default: {}", COLS, SPAN_DEF);
148                                 colSpan = SPAN_DEF;
149                         }
150                 }
151                 
152                 if(log.isDebugEnabled()) {
153                         log.debug("rows: {}", rowSpan);
154                         log.debug("cols: {}", colSpan);
155                         log.debug("delete: {}", delete);
156                         log.debug("block: {}", block);
157                 }
158
159                 // 判定
160                 boolean result;
161                 Object elResult = elMgr.evaluate(expression);
162                 if(elResult == null) {
163                         log.debug("evaluate result is null");
164                         result = false;
165                 }
166                 else if(elResult instanceof Boolean) {
167                         result = (boolean) elResult;
168                 }
169                 else {
170                         result = true;
171                 }
172                 log.debug("evaluate result: {}", result);
173
174                 // 判定falseの場合、範囲の操作
175                 if(!result) {
176                         if(delete == null) {
177                                 log.debug("{} is null set default: {}", DELETE, LEFT);
178                                 delete = LEFT;
179                         }
180                         else if(!LEFT.equalsIgnoreCase(delete) && !UP.equalsIgnoreCase(delete) && !CLEAR.equalsIgnoreCase(delete)) {
181                                 log.warn("{} is illegal argument. set default: {}", DELETE, LEFT);
182                                 delete = LEFT;
183                         }
184                         else {
185                                 log.debug("delete: {}", delete);
186                                 delete = delete.toLowerCase().trim();
187                         }
188                         
189                         switch(delete) {
190                         // クリア
191                         case CLEAR:
192                                 ExcelUtil.clearRange(sheet, (new CellRangeAddress(cell.getRowIndex(), cell.getRowIndex() + rowSpan - 1, cell.getColumnIndex(), cell.getColumnIndex() + colSpan - 1)), false, false);
193                                 break;
194                         // 左詰め
195                         case LEFT:
196                                 // IF範囲以降をずらす
197                                 ExcelUtil.shift(sheet, new CellRangeAddress(cell.getRowIndex(), cell.getRowIndex() + rowSpan - 1, cell.getColumnIndex() + colSpan, cell.getColumnIndex() + colSpan), COL, -colSpan, block);
198                                 break;
199                         // 上詰め
200                         case UP:
201                                 // IF範囲以降をずらす
202                                 ExcelUtil.shift(sheet, new CellRangeAddress(cell.getRowIndex() + rowSpan, cell.getRowIndex() + rowSpan, cell.getColumnIndex(), cell.getColumnIndex() + colSpan - 1), ROW, -rowSpan, block);
203                         }
204                 }
205                 log.trace("parse end");
206         }
207 }