View Javadoc
1   /*
2    * (c) Copyright 2006-2020 by rapiddweller GmbH & Volker Bergmann. All rights reserved.
3    *
4    * Redistribution and use in source and binary forms, with or without
5    * modification, is permitted under the terms of the
6    * GNU General Public License.
7    *
8    * For redistributing this software or a derivative work under a license other
9    * than the GPL-compatible Free Software License as defined by the Free
10   * Software Foundation or approved by OSI, you must first obtain a commercial
11   * license to this software product from rapiddweller GmbH & Volker Bergmann.
12   *
13   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
14   * WITHOUT A WARRANTY OF ANY KIND. ALL EXPRESS OR IMPLIED CONDITIONS,
15   * REPRESENTATIONS AND WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF
16   * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE
17   * HEREBY EXCLUDED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
18   * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
19   * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
20   * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
21   * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
22   * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
23   * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
24   * POSSIBILITY OF SUCH DAMAGE.
25   */
26  
27  package com.rapiddweller.platform.xls;
28  
29  import com.rapiddweller.benerator.consumer.FileExporter;
30  import com.rapiddweller.benerator.consumer.FormattingConsumer;
31  import com.rapiddweller.common.BeanUtil;
32  import com.rapiddweller.common.ConfigurationError;
33  import com.rapiddweller.common.IOUtil;
34  import com.rapiddweller.format.xls.XLSUtil;
35  import com.rapiddweller.model.data.ComponentDescriptor;
36  import com.rapiddweller.model.data.Entity;
37  import com.rapiddweller.model.data.SimpleTypeDescriptor;
38  import com.rapiddweller.platform.csv.CSVEntityExporter;
39  import com.rapiddweller.script.PrimitiveType;
40  import org.apache.logging.log4j.LogManager;
41  import org.apache.logging.log4j.Logger;
42  import org.apache.poi.hssf.usermodel.HSSFCell;
43  import org.apache.poi.hssf.usermodel.HSSFCellStyle;
44  import org.apache.poi.hssf.usermodel.HSSFDataFormat;
45  import org.apache.poi.hssf.usermodel.HSSFRichTextString;
46  import org.apache.poi.hssf.usermodel.HSSFRow;
47  import org.apache.poi.hssf.usermodel.HSSFSheet;
48  import org.apache.poi.hssf.usermodel.HSSFWorkbook;
49  import org.apache.poi.ss.usermodel.CellStyle;
50  
51  import java.io.File;
52  import java.io.FileNotFoundException;
53  import java.io.FileOutputStream;
54  import java.sql.Time;
55  import java.sql.Timestamp;
56  import java.util.Date;
57  import java.util.Map;
58  import java.util.Map.Entry;
59  import java.util.Set;
60  
61  /**
62   * Exports entities to Excel sheets.<br/><br/>
63   * Created at 07.05.2008 13:31:15
64   *
65   * @author Volker Bergmann
66   * @since 0.5.3
67   */
68  public class XLSEntityExporter extends FormattingConsumer
69      implements FileExporter {
70  
71    private static final Logger logger =
72        LogManager.getLogger(CSVEntityExporter.class);
73  
74    // defaults --------------------------------------------------------------------------------------------------------
75  
76    private static final String DEFAULT_URI = "export.xls";
77  
78    // attributes ------------------------------------------------------------------------------------------------------
79  
80    private String uri;
81    private HSSFWorkbook workbook;
82  
83    // constructors ----------------------------------------------------------------------------------------------------
84  
85    /**
86     * Instantiates a new Xls entity exporter.
87     */
88    public XLSEntityExporter() {
89      this(DEFAULT_URI);
90    }
91  
92    /**
93     * Instantiates a new Xls entity exporter.
94     *
95     * @param uri the uri
96     */
97    public XLSEntityExporter(String uri) {
98      this.uri = uri;
99      setDatePattern("m/d/yy");
100     setDecimalPattern("#,##0.##");
101     setIntegralPattern("0");
102     setTimePattern("h:mm:ss");
103     setTimestampPattern("m/d/yy h:mm");
104   }
105 
106   // properties ------------------------------------------------------------------------------------------------------
107 
108   private static Set<Entry<String, Object>> getComponents(Entity entity) {
109     return entity.getComponents().entrySet();
110   }
111 
112   @Override
113   public String getUri() {
114     return uri;
115   }
116 
117   // Consumer interface ----------------------------------------------------------------------------------------------
118 
119   /**
120    * Sets uri.
121    *
122    * @param uri the uri
123    */
124   public void setUri(String uri) {
125     this.uri = uri;
126   }
127 
128   @Override
129   public void startProductConsumption(Object object) {
130     logger.debug("exporting {}", object);
131     if (!(object instanceof Entity)) {
132       throw new IllegalArgumentException("Expecting Entity");
133     }
134     Entity../../../../com/rapiddweller/model/data/Entity.html#Entity">Entity entity = (Entity) object;
135     HSSFSheet sheet = getOrCreateSheet(entity);
136     HSSFRow row = sheet.createRow(sheet.getLastRowNum() + 1);
137     int i = 0;
138     for (Map.Entry<String, Object> component : getComponents(entity)) {
139       render(row, i++, component.getValue());
140     }
141   }
142 
143   // private helpers -------------------------------------------------------------------------------------------------
144 
145   @Override
146   public void close() {
147     FileOutputStream out = null;
148     try {
149       if (workbook == null) {
150         workbook =
151             new HSSFWorkbook(); // if no data was added, create an empty Excel document
152       } else {
153         XLSUtil.autoSizeColumns(workbook);
154       }
155 
156       File directory = new File(uri);
157       // check if path exists, if not make sure it exists
158       if (directory.getParent() != null
159           && !directory.isDirectory()
160           && !directory.getParentFile().exists()) {
161         boolean result = directory.getParentFile().mkdirs();
162         if (!result) {
163           throw new ConfigurationError("filepath does not exists and can not be created ...");
164         }
165       }
166 
167       // Write the output to a file
168       out = new FileOutputStream(uri);
169 
170 
171       workbook.write(out);
172     } catch (FileNotFoundException e) {
173       throw new ConfigurationError(e);
174     } catch (Exception e) {
175       throw new RuntimeException(e);
176     } finally {
177       IOUtil.close(out);
178     }
179   }
180 
181   private HSSFSheet getOrCreateSheet(Entity entity) {
182     // create file
183     if (workbook == null) {
184       createWorkbook();
185     }
186     String sheetName = entity.type();
187     HSSFSheet sheet = workbook.getSheet(sheetName);
188     if (sheet == null) {
189       sheet = workbook.createSheet(sheetName);
190       writeHeaderRow(entity, sheet);
191     }
192     return sheet;
193   }
194 
195   private void createWorkbook() {
196     this.workbook = new HSSFWorkbook();
197     HSSFCellStyle dateCellStyle = workbook.createCellStyle();
198     HSSFDataFormat format = workbook.createDataFormat();
199     short dateFormat = format.getFormat(getDatePattern());
200     dateCellStyle.setDataFormat(dateFormat);
201   }
202 
203   private void writeHeaderRow(Entity entity, HSSFSheet sheet) {
204     HSSFRow headerRow = sheet.createRow(0);
205     int colnum = 0;
206     for (Map.Entry<String, Object> component : getComponents(entity)) {
207       String componentName = component.getKey();
208       headerRow.createCell(colnum)
209           .setCellValue(new HSSFRichTextString(componentName));
210       ComponentDescriptor cd =
211           entity.descriptor().getComponent(componentName);
212       PrimitiveType primitiveType;
213       if (cd.getTypeDescriptor() instanceof SimpleTypeDescriptor) {
214         primitiveType = ((SimpleTypeDescriptor) cd.getTypeDescriptor())
215             .getPrimitiveType();
216       } else {
217         throw new UnsupportedOperationException(
218             "Can only export simple type attributes, " +
219                 "failed to export " + entity.type() + '.' +
220                 cd.getName());
221       }
222       Class<?> javaType =
223           (primitiveType != null ? primitiveType.getJavaType() :
224               String.class);
225       String formatString = null;
226       if (BeanUtil.isIntegralNumberType(javaType)) {
227         formatString = getIntegralPattern();
228       } else if (BeanUtil.isDecimalNumberType(javaType)) {
229         formatString = getDecimalPattern();
230       } else if (Time.class.isAssignableFrom(javaType)) {
231         formatString = getTimePattern();
232       } else if (Timestamp.class.isAssignableFrom(javaType)) {
233         formatString = getTimestampPattern();
234       } else if (Date.class.isAssignableFrom(javaType)) {
235         formatString = getDatePattern();
236       }
237       if (formatString != null) {
238         HSSFDataFormat dataFormat = workbook.createDataFormat();
239         CellStyle columnStyle = workbook.createCellStyle();
240         columnStyle.setDataFormat(dataFormat.getFormat(formatString));
241         sheet.setDefaultColumnStyle(colnum, columnStyle);
242       }
243       colnum++;
244     }
245   }
246 
247   private void render(HSSFRow row, int column, Object value) {
248     HSSFCell cell = row.createCell(column);
249     if (value instanceof Number) {
250       cell.setCellValue(((Number) value).doubleValue());
251     } else if (value instanceof Date) {
252       cell.setCellValue((Date) value);
253     } else if (value instanceof Boolean) {
254       cell.setCellValue((Boolean) value);
255     } else {
256       String s = plainConverter.convert(value);
257       cell.setCellValue(new HSSFRichTextString(s));
258     }
259   }
260 
261   // java.lang.Object overrides --------------------------------------------------------------------------------------
262 
263   @Override
264   public String toString() {
265     return getClass().getSimpleName() + '(' + uri + ")";
266   }
267 
268   @Override
269   public int hashCode() {
270     return uri.hashCode();
271   }
272 
273   @Override
274   public boolean equals(Object obj) {
275     if (this == obj) {
276       return true;
277     }
278     if (obj == null || getClass() != obj.getClass()) {
279       return false;
280     }
281     XLSEntityExporter../com/rapiddweller/platform/xls/XLSEntityExporter.html#XLSEntityExporter">XLSEntityExporter that = (XLSEntityExporter) obj;
282     return (this.uri.equals(that.uri));
283   }
284 
285 }