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.engine.BeneratorContext;
30  import com.rapiddweller.benerator.engine.DefaultBeneratorContext;
31  import com.rapiddweller.common.Context;
32  import com.rapiddweller.common.Converter;
33  import com.rapiddweller.common.IOUtil;
34  import com.rapiddweller.common.context.ContextAware;
35  import com.rapiddweller.common.converter.NoOpConverter;
36  import com.rapiddweller.format.DataContainer;
37  import com.rapiddweller.format.DataIterator;
38  import com.rapiddweller.model.data.ComplexTypeDescriptor;
39  import com.rapiddweller.model.data.Entity;
40  import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
41  import org.apache.poi.ss.usermodel.Sheet;
42  import org.apache.poi.ss.usermodel.Workbook;
43  import org.apache.poi.ss.usermodel.WorkbookFactory;
44  
45  import java.io.IOException;
46  import java.util.ArrayList;
47  import java.util.List;
48  
49  /**
50   * Iterates an Excel sheet and maps its rows to {@link Entity} instances.<br/>
51   * <br/>
52   * Created at 27.01.2009 21:38:31
53   *
54   * @author Volker Bergmann
55   * @since 0.5.8
56   */
57  public class AllSheetsXLSEntityIterator
58      implements DataIterator<Entity>, ContextAware {
59  
60    private final String uri;
61  
62    private final Workbook workbook;
63  
64    private final boolean formatted;
65    private boolean rowBased;
66    private final String emptyMarker;
67  
68    private final Converter<String, ?> preprocessor;
69    private DataIterator<Entity> source;
70    private BeneratorContext context;
71  
72    private final ComplexTypeDescriptor entityDescriptor;
73  
74    private int sheetNo;
75  
76    // constructors ----------------------------------------------------------------------------------------------------
77  
78    /**
79     * Instantiates a new All sheets xls entity iterator.
80     *
81     * @param uri the uri
82     * @throws IOException            the io exception
83     * @throws InvalidFormatException the invalid format exception
84     */
85    public AllSheetsXLSEntityIterator(String uri)
86        throws IOException, InvalidFormatException {
87      this(uri, new NoOpConverter<>(), null, false);
88    }
89  
90    /**
91     * Instantiates a new All sheets xls entity iterator.
92     *
93     * @param uri              the uri
94     * @param preprocessor     the preprocessor
95     * @param entityDescriptor the entity descriptor
96     * @param formatted        the formatted
97     * @throws IOException the io exception
98     */
99    public AllSheetsXLSEntityIterator(String uri,
100                                     Converter<String, ?> preprocessor,
101                                     ComplexTypeDescriptor entityDescriptor,
102                                     boolean formatted)
103       throws IOException {
104     this.uri = uri;
105     this.preprocessor = preprocessor;
106     this.entityDescriptor = entityDescriptor;
107     this.rowBased = (entityDescriptor != null &&
108         entityDescriptor.isRowBased() != null ?
109         entityDescriptor.isRowBased() : true);
110     this.emptyMarker = (entityDescriptor != null &&
111         entityDescriptor.getEmptyMarker() != null ?
112         entityDescriptor.getEmptyMarker() : null);
113     this.workbook =
114         WorkbookFactory.create(IOUtil.getInputStreamForURI(uri));
115     this.sheetNo = -1;
116     this.formatted = formatted;
117   }
118 
119   // properties ------------------------------------------------------------------------------------------------------
120 
121   /**
122    * Parse all list.
123    *
124    * @param uri          the uri
125    * @param preprocessor the preprocessor
126    * @param formatted    the formatted
127    * @return the list
128    * @throws IOException            the io exception
129    * @throws InvalidFormatException the invalid format exception
130    */
131   public static List<Entity> parseAll(String uri,
132                                       Converter<String, ?> preprocessor,
133                                       boolean formatted)
134       throws IOException, InvalidFormatException {
135     List<Entity> list = new ArrayList<>();
136     AllSheetsXLSEntityIterator iterator =
137         new AllSheetsXLSEntityIterator(uri, preprocessor, null,
138             formatted);
139     iterator.setContext(new DefaultBeneratorContext());
140     DataContainer<Entity> container = new DataContainer<>();
141     while ((container = iterator.next(container)) != null) {
142       list.add(container.getData());
143     }
144     return list;
145   }
146 
147   /**
148    * Sets row based.
149    *
150    * @param rowBased the row based
151    */
152   public void setRowBased(boolean rowBased) {
153     this.rowBased = rowBased;
154   }
155 
156 
157   // ContextAware interface implementation ---------------------------------------------------------------------------
158 
159   /**
160    * Gets uri.
161    *
162    * @return the uri
163    */
164   public String getUri() {
165     return uri;
166   }
167 
168 
169   // DataSource interface implementation -----------------------------------------------------------------------------
170 
171   @Override
172   public void setContext(Context context) {
173     this.context = (BeneratorContext) context;
174   }
175 
176   @Override
177   public Class<Entity> getType() {
178     return Entity.class;
179   }
180 
181   @Override
182   public synchronized DataContainer<Entity> next(
183       DataContainer<Entity> container) {
184     if (sheetNo == -1) {
185       nextSheet();
186     }
187     DataContainer<Entity> result;
188     do {
189       if (source == null) {
190         return null;
191       }
192       result = source.next(container);
193       if (result == null) {
194         nextSheet();
195       }
196     } while (source != null && result == null);
197     return result;
198   }
199 
200 
201   // convenience methods ---------------------------------------------------------------------------------------------
202 
203   @Override
204   public synchronized void close() {
205     IOUtil.close(source);
206   }
207 
208 
209   // java.lang.Object overrides --------------------------------------------------------------------------------------
210 
211   @Override
212   public String toString() {
213     return getClass().getSimpleName() + "[" + uri + "]";
214   }
215 
216   // private helpers -------------------------------------------------------------------------------------------------
217 
218   private void nextSheet() {
219     // check if a sheet is available
220     if (sheetNo >= workbook.getNumberOfSheets() - 1) {
221       source = null;
222       return;
223     }
224 
225     // if a sheet was already opened, then close it
226     if (source != null) {
227       IOUtil.close(source);
228     }
229 
230     // select sheet
231     this.sheetNo++;
232 
233     // create iterator
234     Sheet sheet = workbook.getSheetAt(sheetNo);
235     source = new SingleSheetXLSEntityIterator(sheet, preprocessor,
236         entityDescriptor, context, rowBased, formatted, emptyMarker);
237   }
238 
239 }