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