View Javadoc
1   /*
2    * Tethys: GUI Utilities
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.tethys.core.control;
18  
19  import io.github.tonywasher.joceanus.oceanus.base.OceanusException;
20  import io.github.tonywasher.joceanus.oceanus.logger.OceanusLogManager;
21  import io.github.tonywasher.joceanus.oceanus.logger.OceanusLogger;
22  import io.github.tonywasher.joceanus.tethys.api.dialog.TethysUIFileSelector;
23  import io.github.tonywasher.joceanus.tethys.core.base.TethysUIDataException;
24  import io.github.tonywasher.joceanus.tethys.core.factory.TethysUICoreFactory;
25  import org.jsoup.Jsoup;
26  import org.jsoup.nodes.Document;
27  import org.jsoup.nodes.Document.OutputSettings;
28  import org.jsoup.nodes.Element;
29  import org.jsoup.nodes.Entities.EscapeMode;
30  import org.jsoup.select.Elements;
31  
32  import java.io.File;
33  import java.io.IOException;
34  import java.io.PrintWriter;
35  import java.nio.charset.StandardCharsets;
36  
37  /**
38   * HTML to File.
39   */
40  public class TethysUICoreHTMLToFile {
41      /**
42       * The logger.
43       */
44      private static final OceanusLogger LOGGER = OceanusLogManager.getLogger(TethysUICoreHTMLToFile.class);
45  
46      /**
47       * Link element name.
48       */
49      private static final String ELEMENT_A = "a";
50  
51      /**
52       * HRef attribute name.
53       */
54      private static final String ATTR_HREF = "href";
55  
56      /**
57       * Division element name.
58       */
59      private static final String ELEMENT_DIV = "div";
60  
61      /**
62       * Style element name.
63       */
64      private static final String ELEMENT_STYLE = "style";
65  
66      /**
67       * The Gui Factory.
68       */
69      private final TethysUICoreFactory<?> theFactory;
70  
71      /**
72       * The HTML Manager.
73       */
74      private final TethysUICoreHTMLManager theHTMLManager;
75  
76      /**
77       * The File Selector.
78       */
79      private TethysUIFileSelector theFileSelector;
80  
81      /**
82       * Constructor.
83       *
84       * @param pFactory     the GUI Factory
85       * @param pHTMLManager the HTML Manager
86       */
87      public TethysUICoreHTMLToFile(final TethysUICoreFactory<?> pFactory,
88                                    final TethysUICoreHTMLManager pHTMLManager) {
89          /* Store parameters */
90          theFactory = pFactory;
91          theHTMLManager = pHTMLManager;
92      }
93  
94      /**
95       * Initialise file selector.
96       *
97       * @return the file selector
98       */
99      private TethysUIFileSelector initFileSelector() {
100         final TethysUIFileSelector myFileSelector = theFactory.dialogFactory().newFileSelector();
101         myFileSelector.setUseSave(true);
102         myFileSelector.setExtension(".html");
103         return myFileSelector;
104     }
105 
106     /**
107      * Write document to file.
108      */
109     public void writeToFile() {
110         try {
111             /* Make sure that the file Selector is initialised */
112             if (theFileSelector == null) {
113                 theFileSelector = initFileSelector();
114             }
115 
116             /* Select File */
117             final File myFile = theFileSelector.selectFile();
118             if (myFile != null) {
119                 writeToFile(myFile);
120             }
121         } catch (OceanusException e) {
122             LOGGER.error("Failed to write to file", e);
123         }
124     }
125 
126     /**
127      * Write document to file.
128      *
129      * @param pFile the file to write to
130      * @throws OceanusException on error
131      */
132     private void writeToFile(final File pFile) throws OceanusException {
133         /* Create the document */
134         final Document myDoc = createXMLDocument(theHTMLManager.getHTMLString(), theHTMLManager.getProcessedCSS());
135 
136         /* Write the document to the file */
137         writeDocumentToFile(myDoc, pFile);
138     }
139 
140     /**
141      * Parse XML document.
142      *
143      * @param pXML        the XML String
144      * @param pStyleSheet the styleSheet
145      * @return the document
146      */
147     private static Document createXMLDocument(final String pXML,
148                                               final String pStyleSheet) {
149         /* Parse the document */
150         final Document myDoc = Jsoup.parse(pXML);
151 
152         /* Adjust the outputSettings */
153         final OutputSettings mySettings = myDoc.outputSettings();
154         mySettings.charset(StandardCharsets.UTF_8);
155         mySettings.escapeMode(EscapeMode.extended);
156         mySettings.prettyPrint(true);
157 
158         /* Create the style element */
159         final Element myElement = myDoc.createElement(ELEMENT_STYLE);
160         myElement.text(pStyleSheet);
161 
162         /* Obtain the head and add a style element */
163         final Element myHead = myDoc.head();
164         myHead.appendChild(myElement);
165 
166         /* Obtain all link elements */
167         final Elements myLinks = myDoc.getElementsByTag(ELEMENT_A);
168         myLinks.forEach(l -> {
169             /* Remove reference attribute and rename to division */
170             l.attributes().remove(ATTR_HREF);
171             l.tagName(ELEMENT_DIV);
172         });
173 
174         /* Return the document */
175         return myDoc;
176     }
177 
178     /**
179      * Write Document to file.
180      *
181      * @param pDoc  the document to write
182      * @param pFile the file to write to
183      * @throws OceanusException on error
184      */
185     private static void writeDocumentToFile(final Document pDoc,
186                                             final File pFile) throws OceanusException {
187         /* Protect the write */
188         try (PrintWriter myWriter = new PrintWriter(pFile, StandardCharsets.UTF_8.name())) {
189             /* Format the XML and write to stream */
190             final String myHTML = pDoc.outerHtml();
191             myWriter.print(myHTML);
192 
193         } catch (IOException e) {
194             throw new TethysUIDataException("Failed to output XML", e);
195         }
196     }
197 }