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.factory.GordianFactory.GordianFactoryLock;
21  import io.github.tonywasher.joceanus.gordianknot.api.zip.GordianZipFactory;
22  import io.github.tonywasher.joceanus.gordianknot.api.zip.GordianZipLock;
23  import io.github.tonywasher.joceanus.gordianknot.api.zip.GordianZipWriteFile;
24  import io.github.tonywasher.joceanus.metis.toolkit.MetisToolkit;
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.FileOutputStream;
40  import java.io.IOException;
41  import java.io.OutputStream;
42  import java.util.ArrayList;
43  import java.util.List;
44  
45  /**
46   * Write control for spreadsheets.
47   *
48   * @author Tony Washer
49   */
50  public abstract class PrometheusSheetWriter {
51      /**
52       * Gui Factory.
53       */
54      private final TethysUIFactory<?> theGuiFactory;
55  
56      /**
57       * Report.
58       */
59      private final TethysUIThreadStatusReport theReport;
60  
61      /**
62       * Writable spreadsheet.
63       */
64      private PrometheusSheetWorkBook theWorkBook;
65  
66      /**
67       * The DataSet.
68       */
69      private PrometheusDataSet theData;
70  
71      /**
72       * The WorkSheets.
73       */
74      private List<PrometheusSheetDataItem<?>> theSheets;
75  
76      /**
77       * Constructor.
78       *
79       * @param pFactory the gui factory
80       * @param pReport  the report
81       */
82      protected PrometheusSheetWriter(final TethysUIFactory<?> pFactory,
83                                      final TethysUIThreadStatusReport pReport) {
84          theGuiFactory = pFactory;
85          theReport = pReport;
86      }
87  
88      /**
89       * get report.
90       *
91       * @return the report
92       */
93      protected TethysUIThreadStatusReport getReport() {
94          return theReport;
95      }
96  
97      /**
98       * get workbook.
99       *
100      * @return the workbook
101      */
102     protected PrometheusSheetWorkBook getWorkBook() {
103         return theWorkBook;
104     }
105 
106     /**
107      * get dataSet.
108      *
109      * @return the dataSet
110      */
111     public PrometheusDataSet getData() {
112         return theData;
113     }
114 
115     /**
116      * Add Sheet to list.
117      *
118      * @param pSheet the sheet
119      */
120     protected void addSheet(final PrometheusSheetDataItem<?> pSheet) {
121         theSheets.add(pSheet);
122     }
123 
124     /**
125      * Create a Backup Workbook.
126      *
127      * @param pData Data to write out
128      * @param pFile the backup file to write to
129      * @param pType the workBookType
130      * @throws OceanusException on error
131      */
132     public void createBackup(final PrometheusDataSet pData,
133                              final File pFile,
134                              final PrometheusSheetWorkBookType pType) throws OceanusException {
135         boolean writeFailed = false;
136         try {
137             createBackup(pData, new FileOutputStream(pFile), pType);
138         } catch (IOException
139                  | OceanusException e) {
140             writeFailed = true;
141             throw new PrometheusIOException("Failed to create backup Workbook", e);
142         } finally {
143             /* Try to delete the file if required */
144             if (writeFailed) {
145                 MetisToolkit.cleanUpFile(pFile);
146             }
147         }
148     }
149 
150     /**
151      * Create a Backup Workbook.
152      *
153      * @param pData      Data to write out
154      * @param pZipStream the backup file to write to
155      * @param pType      the workBookType
156      * @throws OceanusException on error
157      */
158     public void createBackup(final PrometheusDataSet pData,
159                              final OutputStream pZipStream,
160                              final PrometheusSheetWorkBookType pType) throws OceanusException {
161         /* Obtain the active profile */
162         OceanusProfile myTask = theReport.getActiveTask();
163         myTask = myTask.startTask("Writing");
164 
165         /* Protect against exceptions */
166         try {
167             /* Create a similar security control */
168             final PrometheusSecurityPasswordManager myPasswordMgr = pData.getPasswordMgr();
169             final GordianFactoryLock myBase = pData.getFactoryLock();
170             final GordianFactoryLock myLock = myPasswordMgr.similarFactoryLock(myBase);
171             final GordianZipFactory myZips = myPasswordMgr.getSecurityFactory().getZipFactory();
172             final GordianZipLock myZipLock = myZips.zipLock(myLock);
173 
174             /* Assume failure */
175             final String myName = PrometheusSpreadSheet.FILE_NAME + pType.getExtension();
176 
177             /* Protect the workbook access */
178             try (GordianZipWriteFile myZipFile = myZips.createZipFile(myZipLock, pZipStream);
179                  OutputStream myStream = myZipFile.createOutputStream(new File(myName), false)) {
180                 /* Record the DataSet */
181                 theData = pData;
182 
183                 /* Initialise the WorkBook */
184                 initialiseWorkBook(pType);
185 
186                 /* Write the data to the work book */
187                 writeWorkBook(myStream);
188 
189             } catch (IOException
190                      | OceanusException e) {
191                 /* Report the error */
192                 throw new PrometheusIOException("Failed to create Backup Workbook", e);
193             }
194         } catch (GordianException e) {
195             throw new PrometheusSecurityException(e);
196         }
197 
198         /* Complete task */
199         myTask.end();
200     }
201 
202     /**
203      * Register sheets.
204      */
205     protected abstract void registerSheets();
206 
207     /**
208      * Create the list of sheets to write.
209      *
210      * @param pType the workBookType
211      * @throws OceanusException on error
212      */
213     private void initialiseWorkBook(final PrometheusSheetWorkBookType pType) throws OceanusException {
214         /* Create the workbook attached to the output stream */
215         theWorkBook = PrometheusSheetProvider.newWorkBook(pType);
216 
217         /* Initialise the list */
218         theSheets = new ArrayList<>();
219 
220         /* Loop through the list types */
221         for (PrometheusCryptographyDataType myType : PrometheusCryptographyDataType.values()) {
222             /* Create the sheet */
223             theSheets.add(newSheet(myType));
224         }
225 
226         /* register additional sheets */
227         registerSheets();
228     }
229 
230     /**
231      * Create new sheet of required type.
232      *
233      * @param pListType the list type
234      * @return the new sheet
235      */
236     private PrometheusSheetDataItem<?> newSheet(final PrometheusCryptographyDataType pListType) {
237         /* Switch on list Type */
238         switch (pListType) {
239             case CONTROLDATA:
240                 return new PrometheusSheetControlData(this);
241             case CONTROLKEY:
242                 return new PrometheusSheetControlKey(this);
243             case CONTROLKEYSET:
244                 return new PrometheusSheetControlKeySet(this);
245             case DATAKEYSET:
246                 return new PrometheusSheetDataKeySet(this);
247             default:
248                 throw new IllegalArgumentException(pListType.toString());
249         }
250     }
251 
252     /**
253      * Write the WorkBook.
254      *
255      * @param pStream the output stream
256      * @throws OceanusException on error
257      */
258     private void writeWorkBook(final OutputStream pStream) throws OceanusException {
259         /* Obtain the active profile */
260         final OceanusProfile myTask = theReport.getActiveTask();
261 
262         /* Declare the number of stages */
263         theReport.setNumStages(theSheets.size() + 1);
264 
265         /* Loop through the sheets */
266         for (PrometheusSheetDataItem<?> mySheet : theSheets) {
267             /* Access the next sheet */
268             /* Write data for the sheet */
269             myTask.startTask(mySheet.toString());
270             mySheet.writeSpreadSheet();
271         }
272 
273         /* If we have built all the sheets */
274         theReport.setNewStage("Writing");
275 
276         /* If we have created the workbook OK */
277         /* Write it out to disk and close the stream */
278         myTask.startTask("Saving");
279         theWorkBook.saveToStream(pStream);
280     }
281 }