1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 package com.sun.star.report.pentaho.parser.office;
24 
25 import com.sun.star.report.pentaho.OfficeNamespaces;
26 import com.sun.star.report.pentaho.model.OfficeDocument;
27 import com.sun.star.report.pentaho.model.OfficeStylesCollection;
28 import com.sun.star.report.pentaho.parser.style.OfficeStylesReadHandler;
29 
30 import org.apache.commons.logging.Log;
31 import org.apache.commons.logging.LogFactory;
32 
33 import org.jfree.report.JFreeReport;
34 
35 import org.pentaho.reporting.libraries.resourceloader.Resource;
36 import org.pentaho.reporting.libraries.resourceloader.ResourceException;
37 import org.pentaho.reporting.libraries.resourceloader.ResourceKey;
38 import org.pentaho.reporting.libraries.resourceloader.ResourceKeyCreationException;
39 import org.pentaho.reporting.libraries.resourceloader.ResourceManager;
40 import org.pentaho.reporting.libraries.xmlns.parser.AbstractXmlReadHandler;
41 import org.pentaho.reporting.libraries.xmlns.parser.XmlReadHandler;
42 
43 import org.xml.sax.Attributes;
44 import org.xml.sax.SAXException;
45 
46 /**
47  * This is the root handler for the document context. The
48  * 'office:document-context' element is encountered, if the document is split
49  * into separate files.
50  * <p/>
51  * Alternativly, there is the option to keep everything in one file. The root
52  * element for that format is 'office:document'.
53  */
54 public class DocumentContentReadHandler extends AbstractXmlReadHandler
55 {
56 
57     private static final Log LOGGER = LogFactory.getLog(DocumentContentReadHandler.class);
58     private OfficeDocument report;
59     private FontFaceDeclsReadHandler fontFaceReadHandler;
60     private BodyReadHandler bodyReadHandler;
61     private OfficeStylesCollection officeStylesCollection;
62 
DocumentContentReadHandler()63     public DocumentContentReadHandler()
64     {
65     }
66 
67     /**
68      * Starts parsing.
69      *
70      * @param attrs the attributes.
71      * @throws org.xml.sax.SAXException if there is a parsing error.
72      */
startParsing(final Attributes attrs)73     protected void startParsing(final Attributes attrs)
74             throws SAXException
75     {
76         super.startParsing(attrs);
77         // parse the external 'styles.xml' if it exists
78         // parse the external 'meta.xml' if it exists
79         // parse the external 'settings.xml' if it exists
80         this.report = parseContentXml();
81         this.report.setVirtual(true);
82         this.report.setType("document-content");
83         this.report.setNamespace(OfficeNamespaces.OFFICE_NS);
84         this.report.setVirtual(true);
85         this.officeStylesCollection = parseStylesXml();
86     }
87 
parseStylesXml()88     private OfficeStylesCollection parseStylesXml()
89     {
90         final ResourceKey contextKey = getRootHandler().getContext();
91         final ResourceManager resourceManager = getRootHandler().getResourceManager();
92 
93         try
94         {
95             final ResourceKey key =
96                     resourceManager.deriveKey(contextKey, "styles.xml");
97             final Resource resource =
98                     resourceManager.create(key, contextKey, OfficeStylesCollection.class);
99             final OfficeStylesCollection styles =
100                     (OfficeStylesCollection) resource.getResource();
101             if (styles != null)
102             {
103                 return styles;
104             }
105         }
106         catch (ResourceKeyCreationException e)
107         {
108             // ignore ..
109             LOGGER.debug("Failed to create resource-key for 'styles.xml'. Ignoring.", e);
110         }
111         catch (ResourceException e)
112         {
113             // ignore ..
114             LOGGER.debug("Failed to parse resource for 'styles.xml'. Ignoring.", e);
115         }
116 
117         return new OfficeStylesCollection();
118     }
119 
parseContentXml()120     private OfficeDocument parseContentXml()
121     {
122         // Check whether this is a content.xml.
123         if (!OfficeNamespaces.OFFICE_NS.equals(getUri()) || "document-content".equals(getTagName()))
124         {
125             return new OfficeDocument();
126         }
127 
128         // we may have to parse an existing content.xml.
129         final ResourceKey contextKey = getRootHandler().getContext();
130         final ResourceManager resourceManager = getRootHandler().getResourceManager();
131         try
132         {
133             final ResourceKey key =
134                     resourceManager.deriveKey(contextKey, "content.xml");
135             final Resource resource =
136                     resourceManager.create(key, contextKey, JFreeReport.class);
137             final OfficeDocument doc = (OfficeDocument) resource.getResource();
138             if (doc != null)
139             {
140                 return doc;
141             }
142         }
143         catch (ResourceKeyCreationException e)
144         {
145             // ignore ..
146             LOGGER.debug("Failed to create resource-key for 'content.xml'. Ignoring.");
147         }
148         catch (ResourceException e)
149         {
150             // ignore ..
151             LOGGER.debug("Failed to parse resource for 'content.xml'. Ignoring.");
152         }
153         return new OfficeDocument();
154 
155     }
156 
157     /**
158      * Returns the handler for a child element.
159      *
160      * @param tagName the tag name.
161      * @param atts    the attributes.
162      * @return the handler or null, if the tagname is invalid.
163      *
164      * @throws org.xml.sax.SAXException if there is a parsing error.
165      */
getHandlerForChild(final String uri, final String tagName, final Attributes atts)166     protected XmlReadHandler getHandlerForChild(final String uri,
167             final String tagName,
168             final Attributes atts)
169             throws SAXException
170     {
171         if (OfficeNamespaces.OFFICE_NS.equals(uri))
172         {
173             if ("font-face-decls".equals(tagName))
174             {
175                 if (fontFaceReadHandler == null)
176                 {
177                     fontFaceReadHandler = new FontFaceDeclsReadHandler(officeStylesCollection.getFontFaceDecls());
178                 }
179                 return fontFaceReadHandler;
180             }
181             else if ("automatic-styles".equals(tagName))
182             {
183                 return new OfficeStylesReadHandler(officeStylesCollection.getAutomaticStyles());
184             }
185             else if ("styles".equals(tagName))
186             {
187                 return new OfficeStylesReadHandler(officeStylesCollection.getCommonStyles());
188             }
189             else if ("master-styles".equals(tagName))
190             {
191                 return new MasterStylesReadHandler(officeStylesCollection.getMasterStyles());
192             }
193             else if ("body".equals(tagName))
194             {
195                 bodyReadHandler = new BodyReadHandler();
196                 return bodyReadHandler;
197             }
198         }
199         return null;
200     }
201 
202     /**
203      * Done parsing.
204      *
205      * @throws org.xml.sax.SAXException if there is a parsing error.
206      */
doneParsing()207     protected void doneParsing()
208             throws SAXException
209     {
210         // The office-document is the only node of the report. It allows us to
211         // switch the layout-processing implementation later on.
212 
213         report.setStylesCollection(officeStylesCollection);
214 
215         if (bodyReadHandler != null)
216         {
217             report.addNode(bodyReadHandler.getElement());
218         }
219     }
220 
221     /**
222      * Returns the object for this element or null, if this element does not
223      * create an object.
224      *
225      * @return the object.
226      */
getObject()227     public Object getObject()
228             throws SAXException
229     {
230         return report;
231     }
232 }
233