View Javadoc

1   /*
2    * $Id: TempXMLManager.java 2993 2011-11-24 19:51:48Z andrewinkler $
3    * ============================================================================
4    * Project gluehloch-homepage-core
5    * Copyright (c) 2004-2010 by Andre Winkler. All rights reserved.
6    * ============================================================================
7    *          GNU LESSER GENERAL PUBLIC LICENSE
8    *  TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
9    *
10   *  This library is free software; you can redistribute it and/or
11   *  modify it under the terms of the GNU Lesser General Public
12   *  License as published by the Free Software Foundation; either
13   *  version 2.1 of the License, or (at your option) any later version.
14   *
15   *  This library is distributed in the hope that it will be useful,
16   *  but WITHOUT ANY WARRANTY; without even the implied warranty of
17   *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18   *  Lesser General Public License for more details.
19   *
20   *  You should have received a copy of the GNU Lesser General Public
21   *  License along with this library; if not, write to the Free Software
22   *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
23   *
24   */
25  
26  package de.awtools.homegen.xml;
27  
28  import java.io.ByteArrayOutputStream;
29  import java.io.IOException;
30  import java.io.InputStream;
31  import java.io.UnsupportedEncodingException;
32  import java.util.ArrayList;
33  import java.util.Iterator;
34  import java.util.List;
35  
36  import org.apache.commons.io.IOUtils;
37  import org.apache.commons.lang.StringUtils;
38  import org.dom4j.Document;
39  import org.dom4j.DocumentException;
40  import org.dom4j.Node;
41  import org.dom4j.io.OutputFormat;
42  import org.dom4j.io.SAXReader;
43  import org.dom4j.io.XMLWriter;
44  
45  import de.awtools.homegen.TransformerException;
46  import de.awtools.xml.XMLUtils;
47  
48  /**
49   * Verwaltet die XML/HTML Schnipsel die nach dem ersten Transformationsprozeß
50   * entstanden sind. Die XML/HTML Schnipsel besitzen folgende Struktur:
51   * <pre>
52   *   document/head -> Strukturinformationen: CSS.
53   *   document/body -> Enthält HTML-Code. Wird 1:1 übernommen.
54   * </pre> 
55   *
56   * @version $LastChangedRevision: 2993 $ $LastChangedDate: 2011-11-24 20:51:48 +0100 (Thu, 24 Nov 2011) $
57   * @author by Andre Winkler, $LastChangedBy: andrewinkler $
58   */
59  public final class TempXMLManager {
60  
61      /** Zeichensatzcodierung. */
62      private final String encoding;
63  
64      /** Der 'body' des XML/HTML Schnipsels. */
65      private String body;
66  
67      /** Der 'title' für die HTML Seite. */
68      private String title;
69  
70      /** Die einzubindenden CSS Dateien. */
71      private List<String> cssImports;
72  
73      /**
74       * Konstruktor.
75       *
76       * @param _encoding Zeichensatzkodierung (z.B. UTF-8).
77       */
78      public TempXMLManager(final String _encoding) {
79          encoding = _encoding;
80      }
81  
82      /**
83       * Liefert den 'body' des XML/HTML Schnipsels. Der Inhalt des body Tags
84       * ohne das 'body' Tag selbst.
85       *
86       * @return Der 'body'.
87       */
88      public String getBody() {
89          return body;
90      }
91  
92      /**
93       * Liefert den 'title' für die HTML Seite.
94       *
95       * @return Der 'title'.
96       */
97      public String getTitle() {
98          return title;
99      }
100 
101     /**
102      * Die lokal zu ergänzenden CSS Dateien.
103      *
104      * @return Ein Liste mit CSS Import Anweisungen.
105      */
106     public List<String> getCss() {
107         return cssImports;
108     }
109 
110     /**
111      * Parst einen XML/HTML Schnipsel und stellt dessen Inhalt zur Verfügung.
112      *
113      * @param in Ein InputStream für einen XML/HTML Schnipsel.
114      * @param name Der Name des InputStreams. I.d.R. der Dateiname oder eine
115      *     andere ID, die den InputStream im Fehlerfall identifizieren kann.
116      */
117     public void parse(final InputStream in, final String name) {
118         SAXReader reader = new SAXReader();
119         reader.setStripWhitespaceText(false);
120         try {
121             Document document = reader.read(in);
122             title = extractTitle(document);
123             body = extractBody(document);
124             cssImports = extractCss(document);
125         } catch (DocumentException ex) {
126             throw new TransformerException(name, ex);
127         }
128     }
129 
130     /**
131      * Extrahiert den Titel für die HTML Seite.
132      *
133      * @param document Ein XML Dokument.
134      * @return Der Titel für die HTML Seite.
135      */
136     private String extractTitle(final Document document) {
137         Node node = document.selectSingleNode("//document/head/title");
138         String result = null;
139         if ((node != null) && (!StringUtils.isBlank(node.getText()))) {
140             result = node.getText();
141         }
142         return result;
143     }
144 
145     /**
146      * Extrahiert die CSS Import Informationen.
147      *
148      * @param document Ein XML Dokument.
149      * @return Die CSS Import Anweisungen.
150      */
151     private List<String> extractCss(final Document document) {
152         List<?> nodes = document.selectNodes("//document/head/css");
153         List<String> css = new ArrayList<String>(nodes.size());
154         for (Iterator<?> i = nodes.iterator(); i.hasNext();) {
155             Node node = (Node) i.next();
156             css.add(node.getText());
157         }
158         return css;
159     }
160 
161     /**
162      * Extrahiert den Body und liefert diesen als String zurück ohne das
163      * 'body' Tag selbst.
164      *
165      * @param document Ein XML Dokument.
166      * @return Der Body.
167      */
168     private String extractBody(final Document document) {
169         Node node = document.selectSingleNode("//document/body/.");
170         String result = null;
171 
172         // Möglicherweise ist der Dokumenten-Body leer. Dann die nächsten
173         // Schritte überspringen.
174         if (node != null) {
175             OutputFormat format = OutputFormat.createPrettyPrint();
176             format.setEncoding(encoding);
177             format.setNewlines(true);
178             format.setLineSeparator("\n");
179             format.setTrimText(false);
180 
181             ByteArrayOutputStream baos = new ByteArrayOutputStream();
182             XMLWriter writer = null;
183             try {
184                 writer = new XMLWriter(baos, format);
185                 writer.write(node);
186             } catch (UnsupportedEncodingException ex) {
187                 throw new TransformerException(ex);
188             } catch (IOException ex) {
189                 throw new TransformerException(ex);
190             } finally {
191                 IOUtils.closeQuietly(baos);
192                 XMLUtils.close(writer);
193             }
194 
195             result = StringUtils.replaceOnce(baos.toString(), "<body>", " ");
196             result = StringUtils.replaceOnce(result, "</body>", " ");
197             // @todo Problem:
198             // javascript:menuManager.openHref('./subitem3.html'); wird nach
199             // javascript:menuManager.openHref(&apos;./subitem3.html&apos;)
200             // umgewandelt!
201             result = StringUtils.replace(result, "&apos;", "'");
202         }
203 
204         return result;
205     }
206 
207 }