001    /**
002     * ========================================
003     * JFreeReport : a free Java report library
004     * ========================================
005     *
006     * Project Info:  http://reporting.pentaho.org/
007     *
008     * (C) Copyright 2000-2007, by Object Refinery Limited, Pentaho Corporation and Contributors.
009     *
010     * This library is free software; you can redistribute it and/or modify it under the terms
011     * of the GNU Lesser General Public License as published by the Free Software Foundation;
012     * either version 2.1 of the License, or (at your option) any later version.
013     *
014     * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
015     * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
016     * See the GNU Lesser General Public License for more details.
017     *
018     * You should have received a copy of the GNU Lesser General Public License along with this
019     * library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
020     * Boston, MA 02111-1307, USA.
021     *
022     * [Java is a trademark or registered trademark of Sun Microsystems, Inc.
023     * in the United States and other countries.]
024     *
025     * ------------
026     * $Id: XmlPrintReportTarget.java 3525 2007-10-16 11:43:48Z tmorgner $
027     * ------------
028     * (C) Copyright 2000-2005, by Object Refinery Limited.
029     * (C) Copyright 2005-2007, by Pentaho Corporation.
030     */
031    
032    package org.jfree.report.flow.raw;
033    
034    import java.awt.Image;
035    import java.io.IOException;
036    import java.util.Iterator;
037    import java.util.Map;
038    
039    import org.jfree.layouting.namespace.NamespaceDefinition;
040    import org.jfree.layouting.namespace.Namespaces;
041    import org.jfree.layouting.namespace.NamespaceCollection;
042    import org.jfree.layouting.namespace.DefaultNamespaceCollection;
043    import org.jfree.layouting.util.AttributeMap;
044    import org.jfree.layouting.LibLayoutBoot;
045    import org.jfree.report.DataFlags;
046    import org.jfree.report.DataSourceException;
047    import org.jfree.report.JFreeReportInfo;
048    import org.jfree.report.ReportProcessingException;
049    import org.jfree.report.util.AttributeNameGenerator;
050    import org.jfree.report.flow.ReportJob;
051    import org.jfree.report.flow.ReportStructureRoot;
052    import org.jfree.report.flow.ReportTarget;
053    import org.jfree.report.flow.ReportTargetUtil;
054    import org.jfree.xmlns.common.AttributeList;
055    import org.jfree.xmlns.writer.XmlWriter;
056    import org.jfree.xmlns.writer.XmlWriterSupport;
057    
058    /**
059     * Todo: Document me!
060     *
061     * @author Thomas Morgner
062     * @since 20.03.2007
063     */
064    public class XmlPrintReportTarget implements ReportTarget
065    {
066      private ReportJob reportJob;
067      private XmlWriter writer;
068      private NamespaceCollection namespaces;
069      private AttributeNameGenerator namespacePrefixGenerator;
070    
071      public XmlPrintReportTarget(final ReportJob job,
072                                  final XmlWriter writer)
073      {
074        this.reportJob = job;
075        this.writer = writer;
076    
077        final NamespaceDefinition[] reportNamespaces = Namespaces.createFromConfig
078            (reportJob.getConfiguration(), "org.jfree.report.namespaces.", null);
079        final NamespaceDefinition[] layoutNamespaces = Namespaces.createFromConfig
080            (LibLayoutBoot.getInstance().getGlobalConfig(),
081                "org.jfree.layouting.namespaces.", null);
082        final DefaultNamespaceCollection namespaces = new DefaultNamespaceCollection();
083        namespaces.addDefinitions(reportNamespaces);
084        namespaces.addDefinitions(layoutNamespaces);
085        this.namespaces = namespaces;
086        this.namespacePrefixGenerator = new AttributeNameGenerator();
087      }
088    
089      public ReportJob getReportJob()
090      {
091        return reportJob;
092      }
093    
094      public void startReport(final ReportStructureRoot report)
095          throws DataSourceException, ReportProcessingException
096      {
097        try
098        {
099          writer.writeComment("starting report");
100        }
101        catch (IOException e)
102        {
103          throw new ReportProcessingException("IOError", e);
104        }
105      }
106    
107      public void startElement(final AttributeMap attrs)
108          throws DataSourceException, ReportProcessingException
109      {
110        final String namespace = ReportTargetUtil.getNamespaceFromAttribute(attrs);
111        final String elementType =
112            ReportTargetUtil.getElemenTypeFromAttribute(attrs);
113    
114        try
115        {
116          final AttributeList attrList = buildAttributeList(attrs);
117          validateNamespace(namespace, attrList);
118          writer.writeTag(namespace, elementType, attrList,
119              XmlWriterSupport.OPEN);
120        }
121        catch (IOException e)
122        {
123          throw new ReportProcessingException("IOError", e);
124        }
125      }
126    
127      public void processContent(final DataFlags value)
128          throws DataSourceException, ReportProcessingException
129      {
130        final Object rawvalue = value.getValue();
131        if (rawvalue == null)
132        {
133          return;
134        }
135    
136        // special handler for image (possibly also for URL ..)
137        if (rawvalue instanceof Image)
138        {
139          // do nothing yet. We should define something for that later ..
140          return;
141        }
142    
143        try
144        {
145          final String text = String.valueOf(rawvalue);
146          writer.writeText(XmlWriterSupport.normalize(text, false));
147        }
148        catch (IOException e)
149        {
150          throw new ReportProcessingException("Failed", e);
151        }
152      }
153    
154      public void endElement(final AttributeMap attrs)
155          throws DataSourceException, ReportProcessingException
156      {
157        try
158        {
159          writer.writeCloseTag();
160        }
161        catch (IOException e)
162        {
163          throw new ReportProcessingException("IOError", e);
164        }
165      }
166    
167      public void endReport(final ReportStructureRoot report)
168          throws DataSourceException, ReportProcessingException
169      {
170        try
171        {
172          writer.writeComment("starting report");
173        }
174        catch (IOException e)
175        {
176          throw new ReportProcessingException("IOError", e);
177        }
178      }
179    
180      public NamespaceDefinition getNamespaceByUri(final String uri)
181      {
182        return namespaces.getDefinition(uri);
183      }
184    
185      public void processText(final String text)
186          throws DataSourceException, ReportProcessingException
187      {
188        try
189        {
190          writer.writeText(XmlWriterSupport.normalize(text, false));
191        }
192        catch (IOException e)
193        {
194          throw new ReportProcessingException("IOError", e);
195        }
196      }
197    
198    
199      public void commit()
200          throws ReportProcessingException
201      {
202        try
203        {
204          writer.flush();
205        }
206        catch (IOException e)
207        {
208          throw new ReportProcessingException("Failed to flush", e);
209        }
210      }
211    
212      public String getExportDescriptor()
213      {
214        return "raw/text+xml";
215      }
216    
217      protected AttributeList buildAttributeList(final AttributeMap attrs)
218      {
219        final AttributeList attrList = new AttributeList();
220        final String[] namespaces = attrs.getNameSpaces();
221        for (int i = 0; i < namespaces.length; i++)
222        {
223          final String attrNamespace = namespaces[i];
224          if (isInternalNamespace(attrNamespace))
225          {
226            continue;
227          }
228    
229          final Map localAttributes = attrs.getAttributes(attrNamespace);
230          final Iterator entries = localAttributes.entrySet().iterator();
231          while (entries.hasNext())
232          {
233            final Map.Entry entry = (Map.Entry) entries.next();
234            final String key = String.valueOf(entry.getKey());
235            validateNamespace(attrNamespace, attrList);
236            attrList.setAttribute(attrNamespace, key,
237                String.valueOf(entry.getValue()));
238          }
239        }
240        return attrList;
241      }
242    
243      private void validateNamespace(final String uri, final AttributeList list)
244      {
245        if (writer.isNamespaceDefined(uri))
246        {
247          return;
248        }
249    
250        if (list.isNamespaceUriDefined(uri))
251        {
252          return;
253        }
254    
255        final NamespaceDefinition def = getNamespaceByUri(uri);
256        if (def != null)
257        {
258          final String prefix = def.getPreferredPrefix();
259          if (writer.isNamespacePrefixDefined(prefix) == false &&
260              list.isNamespacePrefixDefined(prefix) == false)
261          {
262            list.addNamespaceDeclaration (prefix, uri);
263          }
264          else
265          {
266            list.addNamespaceDeclaration
267                (namespacePrefixGenerator.generateName(prefix), uri);
268          }
269        }
270        else
271        {
272          list.addNamespaceDeclaration
273              (namespacePrefixGenerator.generateName("auto"), uri);
274        }
275      }
276    
277      private boolean isInternalNamespace(final String namespace)
278      {
279        return JFreeReportInfo.REPORT_NAMESPACE.equals(namespace);
280      }
281    
282    }