PageRenderTime 57ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/drools-decisiontables/src/main/java/org/drools/decisiontable/parser/xls/ExcelParser.java

https://github.com/abhinav681/drools
Java | 276 lines | 219 code | 34 blank | 23 comment | 28 complexity | dfb6123bb8748bdec7b3f0caf1a28d29 MD5 | raw file
Possible License(s): Apache-2.0
  1. /*
  2. * Copyright 2005 JBoss Inc
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. package org.drools.decisiontable.parser.xls;
  17. import java.io.IOException;
  18. import java.io.InputStream;
  19. import java.util.ArrayList;
  20. import java.util.HashMap;
  21. import java.util.List;
  22. import java.util.Locale;
  23. import java.util.Map;
  24. import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
  25. import org.apache.poi.ss.usermodel.Cell;
  26. import org.apache.poi.ss.usermodel.CellValue;
  27. import org.apache.poi.ss.usermodel.DataFormatter;
  28. import org.apache.poi.ss.usermodel.FormulaEvaluator;
  29. import org.apache.poi.ss.usermodel.Row;
  30. import org.apache.poi.ss.usermodel.Sheet;
  31. import org.apache.poi.ss.usermodel.Workbook;
  32. import org.apache.poi.ss.usermodel.WorkbookFactory;
  33. import org.apache.poi.ss.util.CellRangeAddress;
  34. import org.drools.decisiontable.parser.DecisionTableParser;
  35. import org.drools.template.parser.DataListener;
  36. import org.drools.template.parser.DecisionTableParseException;
  37. import org.slf4j.Logger;
  38. import org.slf4j.LoggerFactory;
  39. import static java.lang.String.format;
  40. /**
  41. * Parse an excel spreadsheet, pushing cell info into the SheetListener interface.
  42. */
  43. public class ExcelParser
  44. implements
  45. DecisionTableParser {
  46. private static final Logger log = LoggerFactory.getLogger( ExcelParser.class );
  47. public static final String DEFAULT_RULESHEET_NAME = "Decision Tables";
  48. private Map<String, List<DataListener>> _listeners = new HashMap<String, List<DataListener>>();
  49. private boolean _useFirstSheet;
  50. /**
  51. * Define a map of sheet name to listener handlers.
  52. * @param sheetListeners map of String to SheetListener
  53. */
  54. public ExcelParser( final Map<String, List<DataListener>> sheetListeners ) {
  55. this._listeners = sheetListeners;
  56. }
  57. public ExcelParser( final List<DataListener> sheetListeners ) {
  58. this._listeners.put( ExcelParser.DEFAULT_RULESHEET_NAME,
  59. sheetListeners );
  60. this._useFirstSheet = true;
  61. }
  62. public ExcelParser( final DataListener listener ) {
  63. List<DataListener> listeners = new ArrayList<DataListener>();
  64. listeners.add( listener );
  65. this._listeners.put( ExcelParser.DEFAULT_RULESHEET_NAME,
  66. listeners );
  67. this._useFirstSheet = true;
  68. }
  69. public void parseFile( InputStream inStream ) {
  70. try {
  71. Workbook workbook = WorkbookFactory.create( inStream );
  72. if ( _useFirstSheet ) {
  73. Sheet sheet = workbook.getSheetAt( 0 );
  74. processSheet( sheet, _listeners.get( DEFAULT_RULESHEET_NAME ) );
  75. } else {
  76. for ( String sheetName : _listeners.keySet() ) {
  77. Sheet sheet = workbook.getSheet( sheetName );
  78. if ( sheet == null ) {
  79. throw new IllegalStateException( "Could not find the sheetName (" + sheetName
  80. + ") in the workbook sheetNames." );
  81. }
  82. processSheet( sheet,
  83. _listeners.get( sheetName ) );
  84. }
  85. }
  86. } catch ( InvalidFormatException e ) {
  87. throw new DecisionTableParseException( "An error occurred opening the workbook. It is possible that the encoding of the document did not match the encoding of the reader.",
  88. e );
  89. } catch ( IOException e ) {
  90. throw new DecisionTableParseException( "Failed to open Excel stream, " + "please check that the content is xls97 format.",
  91. e );
  92. }
  93. }
  94. private CellRangeAddress[] getMergedCells( Sheet sheet ) {
  95. CellRangeAddress[] ranges = new CellRangeAddress[ sheet.getNumMergedRegions() ];
  96. for ( int i = 0; i < ranges.length; i++ ) {
  97. ranges[ i ] = sheet.getMergedRegion( i );
  98. }
  99. return ranges;
  100. }
  101. private void processSheet( Sheet sheet,
  102. List<? extends DataListener> listeners ) {
  103. int maxRows = sheet.getLastRowNum();
  104. CellRangeAddress[] mergedRanges = getMergedCells( sheet );
  105. DataFormatter formatter = new DataFormatter( Locale.ENGLISH );
  106. FormulaEvaluator formulaEvaluator = sheet.getWorkbook().getCreationHelper().createFormulaEvaluator();
  107. for ( int i = 0; i <= maxRows; i++ ) {
  108. Row row = sheet.getRow( i );
  109. int lastCellNum = row != null ? row.getLastCellNum() : 0;
  110. newRow( listeners, i, lastCellNum );
  111. for ( int cellNum = 0; cellNum < lastCellNum; cellNum++ ) {
  112. Cell cell = row.getCell( cellNum );
  113. if ( cell == null ) {
  114. continue;
  115. }
  116. double num = 0;
  117. CellRangeAddress merged = getRangeIfMerged( cell,
  118. mergedRanges );
  119. if ( merged != null ) {
  120. Cell topLeft = sheet.getRow( merged.getFirstRow() ).getCell( merged.getFirstColumn() );
  121. newCell( listeners,
  122. i,
  123. cellNum,
  124. formatter.formatCellValue( topLeft ),
  125. topLeft.getColumnIndex() );
  126. } else {
  127. switch ( cell.getCellType() ) {
  128. case Cell.CELL_TYPE_FORMULA:
  129. String cellValue = null;
  130. try {
  131. CellValue cv = formulaEvaluator.evaluate( cell );
  132. cellValue = getCellValue( cv );
  133. newCell( listeners,
  134. i,
  135. cellNum,
  136. cellValue,
  137. DataListener.NON_MERGED );
  138. } catch ( RuntimeException e ) {
  139. // This is thrown if an external link cannot be resolved, so try the cached value
  140. log.warn( "Cannot resolve externally linked value: " + formatter.formatCellValue( cell ) );
  141. String cachedValue = tryToReadCachedValue( cell );
  142. newCell( listeners,
  143. i,
  144. cellNum,
  145. cachedValue,
  146. DataListener.NON_MERGED );
  147. }
  148. break;
  149. case Cell.CELL_TYPE_NUMERIC:
  150. num = cell.getNumericCellValue();
  151. default:
  152. if ( num - Math.round( num ) != 0 ) {
  153. newCell( listeners,
  154. i,
  155. cellNum,
  156. String.valueOf( num ),
  157. DataListener.NON_MERGED );
  158. } else {
  159. newCell( listeners,
  160. i,
  161. cellNum,
  162. formatter.formatCellValue( cell ),
  163. DataListener.NON_MERGED );
  164. }
  165. }
  166. }
  167. }
  168. }
  169. finishSheet( listeners );
  170. }
  171. private String tryToReadCachedValue( Cell cell ) {
  172. DataFormatter formatter = new DataFormatter( Locale.ENGLISH );
  173. String cachedValue;
  174. switch ( cell.getCachedFormulaResultType() ) {
  175. case Cell.CELL_TYPE_NUMERIC:
  176. double num = cell.getNumericCellValue();
  177. if ( num - Math.round( num ) != 0 ) {
  178. cachedValue = String.valueOf( num );
  179. } else {
  180. cachedValue = formatter.formatCellValue( cell );
  181. }
  182. break;
  183. case Cell.CELL_TYPE_STRING:
  184. cachedValue = cell.getStringCellValue();
  185. break;
  186. case Cell.CELL_TYPE_BOOLEAN:
  187. cachedValue = String.valueOf( cell.getBooleanCellValue() );
  188. break;
  189. case Cell.CELL_TYPE_ERROR:
  190. cachedValue = String.valueOf( cell.getErrorCellValue() );
  191. break;
  192. default:
  193. throw new DecisionTableParseException( format( "Can't read cached value for cell[row=%d, col=%d, value=%s]!",
  194. cell.getRowIndex(), cell.getColumnIndex(), cell ) );
  195. }
  196. return cachedValue;
  197. }
  198. private String getCellValue( final CellValue cv ) {
  199. switch ( cv.getCellType() ) {
  200. case Cell.CELL_TYPE_BOOLEAN:
  201. return Boolean.toString( cv.getBooleanValue() );
  202. case Cell.CELL_TYPE_NUMERIC:
  203. return String.valueOf( cv.getNumberValue() );
  204. }
  205. return cv.getStringValue();
  206. }
  207. CellRangeAddress getRangeIfMerged( Cell cell,
  208. CellRangeAddress[] mergedRanges ) {
  209. for ( int i = 0; i < mergedRanges.length; i++ ) {
  210. CellRangeAddress r = mergedRanges[ i ];
  211. if ( r.isInRange( cell.getRowIndex(), cell.getColumnIndex() ) ) {
  212. return r;
  213. }
  214. }
  215. return null;
  216. }
  217. private void finishSheet( List<? extends DataListener> listeners ) {
  218. for ( DataListener listener : listeners ) {
  219. listener.finishSheet();
  220. }
  221. }
  222. private void newRow( List<? extends DataListener> listeners,
  223. int row,
  224. int cols ) {
  225. for ( DataListener listener : listeners ) {
  226. listener.newRow( row,
  227. cols );
  228. }
  229. }
  230. public void newCell( List<? extends DataListener> listeners,
  231. int row,
  232. int column,
  233. String value,
  234. int mergedColStart ) {
  235. for ( DataListener listener : listeners ) {
  236. listener.newCell( row,
  237. column,
  238. value,
  239. mergedColStart );
  240. }
  241. }
  242. }