/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package ro.nextreports.engine.exporter; import com.thoughtworks.xstream.core.util.Base64Encoder; import java.io.PrintStream; import java.io.UnsupportedEncodingException; import java.util.Set; import java.util.HashSet; import java.util.Date; import ro.nextreports.engine.ReleaseInfoAdapter; import ro.nextreports.engine.Report; import ro.nextreports.engine.band.Band; import ro.nextreports.engine.band.BandElement; import ro.nextreports.engine.band.ColumnBandElement; import ro.nextreports.engine.band.ExpressionBandElement; import ro.nextreports.engine.band.FunctionBandElement; import ro.nextreports.engine.band.Hyperlink; import ro.nextreports.engine.band.HyperlinkBandElement; import ro.nextreports.engine.band.ImageBandElement; import ro.nextreports.engine.band.ParameterBandElement; import ro.nextreports.engine.band.ReportBandElement; import ro.nextreports.engine.band.VariableBandElement; import ro.nextreports.engine.queryexec.QueryException; import ro.nextreports.engine.queryexec.QueryResult; import ro.nextreports.engine.util.StringUtil; /** * User: mihai.panaitescu * Date: 05-Mar-2010 * Time: 10:40:00 */ public class XmlExporter extends ResultExporter { // useful to open xml file in excel (excel will see the space character) private String space = "_x0020_"; private static final String DOCUMENT_TAG = "document"; private static final String RECORD_TAG = "record"; private static final String IMAGE_TAG = "image"; private static final String TEXT_TAG = "text"; private static final String lineSeparator = " \r\n"; private PrintStream stream; private int currentRow = resultSetRow; public XmlExporter(ExporterBean bean) { super(bean); } protected void initExport() throws QueryException { stream = createPrintStream(); if (!bean.isSubreport()) { stream.print("<?xml version=\"1.0\" standalone=\"yes\"?>"); stream.print(lineSeparator); stream.print("<" + DOCUMENT_TAG + ">"); stream.print(lineSeparator); stream.print(getMetaData()); } } protected void finishExport() { if (!bean.isSubreport()) { stream.print("</" + DOCUMENT_TAG + ">"); stream.print(lineSeparator); } stream.flush(); if (!bean.isSubreport()) { stream.close(); } } protected void close() { if (!bean.isSubreport()) { stream.close(); } } protected void flush() { if (resultSetRow % FLUSH_ROWS == 0) { flushNow(); } } protected void flushNow() { stream.flush(); } protected Set<CellElement> getIgnoredCells(Band band) { return new HashSet<CellElement>(); } protected void printRawRecord() throws QueryException { QueryResult qr = getResult(); int columns = qr.getColumnCount(); stream.print("\t<" + RECORD_TAG + ">"); stream.print(lineSeparator); for (int i = 0; i < columns; i++) { String name = qr.getColumnName(i); Object value = qr.nextValue(name); // xml tags do not allow space characters name = name.replaceAll(" ", space); stream.print("\t\t<"); stream.print(name); stream.print(">"); stream.print(value); stream.print("</"); stream.print(name); stream.print(">"); stream.print(lineSeparator); } stream.print("\t</" + RECORD_TAG + ">"); stream.print(lineSeparator); } private String getMetaData() { StringBuilder sb = new StringBuilder(); sb.append("\t<meta name=\"author\" content=\""). append(ReleaseInfoAdapter.getCompany()). append("\"/>").append(lineSeparator); sb.append("\t<meta name=\"creator\" content=\""). append("NextReports ").append(ReleaseInfoAdapter.getVersionNumber()). append("\"/>").append(lineSeparator); sb.append("\t<meta name=\"subject\" content=\""). append("Created by NextReports Designer ").append(ReleaseInfoAdapter.getVersionNumber()). append("\"/>").append(lineSeparator); sb.append("\t<meta name=\"date\" content=\""). append(new Date()). append("\"/>").append(lineSeparator); sb.append("\t<meta name=\"keywords\" content=\""). append(ReleaseInfoAdapter.getHome()). append("\"/>").append(lineSeparator); return sb.toString(); } protected void exportCell(String bandName, BandElement bandElement, Object value, int gridRow, int row, int column, int cols, int rowSpan, int colSpan, boolean isImage) { if (bean.isRawPrint()) { return; } if (newRow) { stream.print("\t<" + RECORD_TAG + ">"); stream.print(lineSeparator); } String val; if (isImage) { val = (String) value; } else { val = getStringValue(value, getPattern(bandElement)); // special xml characters val = val.replaceAll("& ", "& "); val = val.replaceAll("<", "<"); val = val.replaceAll(">", ">"); val = val.replaceAll("\"", """); val = val.replaceAll("'", "'"); } stream.print("\t\t"); stream.print(getTag(bandName, row, column, val, rowSpan, colSpan, bandElement, isImage)); stream.print(lineSeparator); if (column == cols-1) { stream.print("\t</" + RECORD_TAG + ">"); stream.print(lineSeparator); if ((colSpan == cols) && (rowSpan > 1)) { for (int i = 0; i < rowSpan - 1; i++) { stream.print(getEmptyRow(colSpan)); } } } } private String getStringValue(Object val, String pattern) { String v = StringUtil.getValueAsString(val, pattern, getReportLanguage()); if (v == null) { return getNullElement(); } return v; } protected void afterRowExport() { } protected String getNullElement() { return ""; } private String getEmptyRow(int colSpan) { StringBuilder sb = new StringBuilder(); sb.append("<").append(RECORD_TAG).append(">"). append(getNullElement()). append("</").append(RECORD_TAG).append(">"). append(lineSeparator); return sb.toString(); } private String getTag(String bandName, int i, int j, String value, int rowSpan, int colSpan, BandElement bandElement, boolean image) { if (bandElement == null) { return getNullElement(); } StringBuilder sb = new StringBuilder(); sb.append(getTag(bandElement, true)); String result = ""; if (image) { if (value != null) { try { byte[] imageBytes = getImage(value); result = getBinaryDataForXml(imageBytes); } catch (Exception e) { // nothing to do } } } else if (bandElement instanceof HyperlinkBandElement) { Hyperlink hyperlink = ((HyperlinkBandElement)bandElement).getHyperlink(); result = hyperlink.getUrl(); } else if (bandElement instanceof ReportBandElement) { Report report = ((ReportBandElement)bandElement).getReport(); ExporterBean eb = null; try { eb = getSubreportExporterBean(report); XmlExporter subExporter = new XmlExporter(eb); subExporter.export(); result = subExporter.getSubreportData(); } catch (Exception e) { e.printStackTrace(); } finally { if ((eb != null) && (eb.getResult() != null)) { eb.getResult().close(); } } } else { result = StringUtil.getValueAsString(value, null, getReportLanguage()); if (result == null) { result = getNullElement(); } } sb.append(result); sb.append(getTag(bandElement, false)); return sb.toString(); } private String getTag(BandElement be, boolean start) { StringBuilder sb = new StringBuilder(); if (start) { sb.append("<"); } else { sb.append("</"); } String tagName; if (be instanceof ColumnBandElement) { tagName = ((ColumnBandElement)be).getColumn(); } else if (be instanceof FunctionBandElement) { tagName = ((FunctionBandElement)be).getFunction(); } else if (be instanceof ExpressionBandElement) { tagName = ((ExpressionBandElement)be).getExpressionName(); } else if (be instanceof HyperlinkBandElement) { tagName = ((HyperlinkBandElement)be).getName(); } else if (be instanceof ImageBandElement) { tagName = IMAGE_TAG; } else if (be instanceof ParameterBandElement) { tagName = ((ParameterBandElement)be).getParameter(); } else if (be instanceof VariableBandElement) { tagName = ((VariableBandElement)be).getVariable(); } else { // static text tagName = TEXT_TAG; } // special xml characters tagName = tagName.replaceAll("& ", "& "); tagName = tagName.replaceAll("<", "<"); tagName = tagName.replaceAll(">", ">"); tagName = tagName.replaceAll("\"", """); tagName = tagName.replaceAll("'", "'"); // space in tag tagName = tagName.replaceAll(" ", space); sb.append(tagName); sb.append(">"); return sb.toString(); } // http://www.javaworld.com/javatips/jw-javatip117.html public String getBinaryDataForXml(byte[] buffer) { StringBuffer hexData = new StringBuffer(); Base64Encoder encoder = new Base64Encoder(); return encoder.encode(buffer); } private String getSubreportData() { try { return subreportStream.toString("UTF-8"); } catch (UnsupportedEncodingException e) { e.printStackTrace(); return ""; } finally { stream.close(); } } }