View Javadoc
1   /*
2    * Prometheus: Application Framework
3    * Copyright 2012-2026. Tony Washer
4    *
5    * Licensed under the Apache License, Version 2.0 (the "License"); you may not
6    * use this file except in compliance with the License.  You may obtain a copy
7    * of the License at
8    *
9    *   http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13   * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
14   * License for the specific language governing permissions and limitations under
15   * the License.
16   */
17  package io.github.tonywasher.joceanus.prometheus.sheets;
18  
19  import io.github.tonywasher.joceanus.gordianknot.api.base.GordianException;
20  import io.github.tonywasher.joceanus.gordianknot.api.zip.GordianZipFactory;
21  import io.github.tonywasher.joceanus.gordianknot.api.zip.GordianZipFileContents;
22  import io.github.tonywasher.joceanus.gordianknot.api.zip.GordianZipFileEntry;
23  import io.github.tonywasher.joceanus.gordianknot.api.zip.GordianZipLock;
24  import io.github.tonywasher.joceanus.gordianknot.api.zip.GordianZipReadFile;
25  import io.github.tonywasher.joceanus.oceanus.base.OceanusException;
26  import io.github.tonywasher.joceanus.oceanus.profile.OceanusProfile;
27  import io.github.tonywasher.joceanus.prometheus.data.PrometheusDataSet;
28  import io.github.tonywasher.joceanus.prometheus.data.PrometheusDataSet.PrometheusCryptographyDataType;
29  import io.github.tonywasher.joceanus.prometheus.exc.PrometheusIOException;
30  import io.github.tonywasher.joceanus.prometheus.exc.PrometheusSecurityException;
31  import io.github.tonywasher.joceanus.prometheus.security.PrometheusSecurityPasswordManager;
32  import io.github.tonywasher.joceanus.prometheus.service.sheet.PrometheusSheetProvider;
33  import io.github.tonywasher.joceanus.prometheus.service.sheet.PrometheusSheetWorkBook;
34  import io.github.tonywasher.joceanus.prometheus.service.sheet.PrometheusSheetWorkBookType;
35  import io.github.tonywasher.joceanus.tethys.api.factory.TethysUIFactory;
36  import io.github.tonywasher.joceanus.tethys.api.thread.TethysUIThreadStatusReport;
37  
38  import java.io.File;
39  import java.io.FileInputStream;
40  import java.io.IOException;
41  import java.io.InputStream;
42  import java.util.ArrayList;
43  import java.util.Iterator;
44  import java.util.List;
45  
46  /**
47   * Load control for spreadsheets.
48   *
49   * @author Tony Washer
50   */
51  public abstract class PrometheusSheetReader {
52      /**
53       * Gui Factory.
54       */
55      private final TethysUIFactory<?> theGuiFactory;
56  
57      /**
58       * Report.
59       */
60      private final TethysUIThreadStatusReport theReport;
61  
62      /**
63       * The password manager.
64       */
65      private final PrometheusSecurityPasswordManager thePasswordMgr;
66  
67      /**
68       * Spreadsheet.
69       */
70      private PrometheusSheetWorkBook theWorkBook;
71  
72      /**
73       * DataSet.
74       */
75      private PrometheusDataSet theData;
76  
77      /**
78       * The WorkSheets.
79       */
80      private List<PrometheusSheetDataItem<?>> theSheets;
81  
82      /**
83       * Constructor.
84       *
85       * @param pFactory     the gui factory
86       * @param pReport      the report
87       * @param pPasswordMgr the password manager
88       */
89      protected PrometheusSheetReader(final TethysUIFactory<?> pFactory,
90                                      final TethysUIThreadStatusReport pReport,
91                                      final PrometheusSecurityPasswordManager pPasswordMgr) {
92          theGuiFactory = pFactory;
93          theReport = pReport;
94          thePasswordMgr = pPasswordMgr;
95      }
96  
97      /**
98       * get report.
99       *
100      * @return the report
101      */
102     protected TethysUIThreadStatusReport getReport() {
103         return theReport;
104     }
105 
106     /**
107      * get data.
108      *
109      * @return the data
110      */
111     public PrometheusDataSet getData() {
112         return theData;
113     }
114 
115     /**
116      * get workbook.
117      *
118      * @return the workbook
119      */
120     protected PrometheusSheetWorkBook getWorkBook() {
121         return theWorkBook;
122     }
123 
124     /**
125      * Add Sheet to list.
126      *
127      * @param pSheet the sheet
128      */
129     protected void addSheet(final PrometheusSheetDataItem<?> pSheet) {
130         theSheets.add(pSheet);
131     }
132 
133     /**
134      * Load a Backup Workbook.
135      *
136      * @param pData DataSet to load into
137      * @param pFile the file to load
138      * @throws OceanusException on error
139      */
140     public void loadBackup(final File pFile,
141                            final PrometheusDataSet pData) throws OceanusException {
142         try {
143             loadBackup(new FileInputStream(pFile), pData, pFile.getName());
144         } catch (IOException e) {
145             throw new PrometheusIOException("Failed to access Backup", e);
146         }
147     }
148 
149     /**
150      * Load a Backup Workbook.
151      *
152      * @param pInStream the zip input stream
153      * @param pData     the data to load into
154      * @param pName     the filename
155      * @throws OceanusException on error
156      */
157     public void loadBackup(final InputStream pInStream,
158                            final PrometheusDataSet pData,
159                            final String pName) throws OceanusException {
160         /* Protect against exceptions */
161         try {
162             /* Start the task */
163             OceanusProfile myTask = theReport.getActiveTask();
164             myTask = myTask.startTask("Loading");
165             theData = pData;
166 
167             /* Access the zip file */
168             final GordianZipFactory myZips = thePasswordMgr.getSecurityFactory().getZipFactory();
169             final GordianZipReadFile myFile = myZips.openZipFile(pInStream);
170 
171             /* Obtain the lock from the file */
172             final GordianZipLock myLock = myFile.getLock();
173 
174             /* Resolve the lock */
175             thePasswordMgr.resolveZipLock(myLock, pName);
176 
177             /* Access ZipFile contents */
178             final GordianZipFileContents myContents = myFile.getContents();
179 
180             /* Loop through the file entries */
181             final Iterator<GordianZipFileEntry> myIterator = myContents.iterator();
182             GordianZipFileEntry myEntry = null;
183             while (myIterator.hasNext()) {
184                 /* Access the entry */
185                 myEntry = myIterator.next();
186 
187                 /* Break loop if we have the right entry */
188                 if (myEntry.getFileName().startsWith(PrometheusSpreadSheet.FILE_NAME)) {
189                     break;
190                 }
191             }
192 
193             /* Load the workBook */
194             loadEntry(myFile, myEntry);
195 
196             /* Complete the task */
197             myTask.end();
198 
199         } catch (GordianException e) {
200             throw new PrometheusSecurityException(e);
201         }
202     }
203 
204     /**
205      * Load a Backup Workbook.
206      *
207      * @param pFile  the zip file
208      * @param pEntry the zip file entry
209      * @throws OceanusException on error
210      */
211     public void loadEntry(final GordianZipReadFile pFile,
212                           final GordianZipFileEntry pEntry) throws OceanusException {
213         /* Protect the workbook retrieval */
214         try (InputStream myStream = pFile.createInputStream(pEntry)) {
215             /* Obtain the active profile */
216             final OceanusProfile myTask = theReport.getActiveTask();
217             myTask.startTask("Parsing");
218 
219             /* Initialise the workbook */
220             initialiseWorkBook(myStream, PrometheusSheetWorkBookType.determineType(pEntry.getFileName()));
221 
222             /* Load the workbook */
223             myTask.startTask("Reading");
224             loadWorkBook();
225 
226             /* Close the Stream to force out errors */
227             myTask.startTask("Closing");
228 
229         } catch (IOException e) {
230             /* Report the error */
231             throw new PrometheusIOException("Failed to load Backup Workbook: " + pEntry.getFileName(), e);
232 
233         } catch (GordianException e) {
234             throw new PrometheusSecurityException(e);
235         }
236     }
237 
238     /**
239      * Register sheets.
240      */
241     protected abstract void registerSheets();
242 
243     /**
244      * Create the list of sheets to load.
245      *
246      * @param pStream the input stream
247      * @param pType   the workBookType
248      * @throws OceanusException on error
249      */
250     private void initialiseWorkBook(final InputStream pStream,
251                                     final PrometheusSheetWorkBookType pType) throws OceanusException {
252         /* Initialise the list */
253         theSheets = new ArrayList<>();
254 
255         /* Loop through the list types */
256         for (PrometheusCryptographyDataType myType : PrometheusCryptographyDataType.values()) {
257             /* Create the sheet */
258             theSheets.add(newSheet(myType));
259         }
260 
261         /* register additional sheets */
262         registerSheets();
263 
264         /* Declare the number of stages */
265         theReport.setNumStages(theSheets.size() + 2);
266 
267         /* Note the stage */
268         theReport.setNewStage("Loading");
269 
270         /* Access the workbook from the stream */
271         theWorkBook = PrometheusSheetProvider.loadFromStream(pType, pStream);
272     }
273 
274     /**
275      * Create new sheet of required type.
276      *
277      * @param pListType the list type
278      * @return the new sheet
279      */
280     private PrometheusSheetDataItem<?> newSheet(final PrometheusCryptographyDataType pListType) {
281         /* Switch on list Type */
282         switch (pListType) {
283             case CONTROLDATA:
284                 return new PrometheusSheetControlData(this);
285             case CONTROLKEY:
286                 return new PrometheusSheetControlKey(this);
287             case CONTROLKEYSET:
288                 return new PrometheusSheetControlKeySet(this);
289             case DATAKEYSET:
290                 return new PrometheusSheetDataKeySet(this);
291             default:
292                 throw new IllegalArgumentException(pListType.toString());
293         }
294     }
295 
296     /**
297      * Load the WorkBook.
298      *
299      * @throws OceanusException on error
300      */
301     private void loadWorkBook() throws OceanusException {
302         /* Obtain the active profile */
303         final OceanusProfile myTask = theReport.getActiveTask();
304 
305         /* Declare the number of stages */
306         theReport.setNumStages(theSheets.size() + 1);
307 
308         /* Loop through the sheets */
309         for (PrometheusSheetDataItem<?> mySheet : theSheets) {
310             /* Access the next sheet */
311             /* Load data for the sheet */
312             myTask.startTask(mySheet.toString());
313             mySheet.loadSpreadSheet();
314         }
315     }
316 }