/* * Rapid Beans Framework: RapidBeanSerializer.java * * Copyright (C) 2009 Martin Bluemel * * Creation Date: 04/02/2006 * * This program is free software; you can redistribute it and/or modify it under the terms of the * GNU Lesser General Public License as published by the Free Software Foundation; * either version 3 of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU Lesser General Public License for more details. * You should have received a copies of the GNU Lesser General Public License and the * GNU General Public License along with this program; if not, see <http://www.gnu.org/licenses/>. */ package org.rapidbeans.core.common; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.StringWriter; import java.io.Writer; import java.net.URL; import java.net.URLConnection; import java.util.Collection; import java.util.List; import org.rapidbeans.core.basic.IdType; import org.rapidbeans.core.basic.Property; import org.rapidbeans.core.basic.PropertyCollection; import org.rapidbeans.core.basic.RapidBean; import org.rapidbeans.core.exception.RapidBeansRuntimeException; import org.rapidbeans.core.type.TypeProperty; import org.rapidbeans.core.type.TypePropertyCollection; import org.rapidbeans.core.util.FileHelper; import org.rapidbeans.core.util.PlatformHelper; /** * Serialize a RapidBeansDocument to a stream / file. * * @author Martin Bluemel */ public final class RapidBeanSerializer { /** * Constructor. */ public RapidBeanSerializer() { } /** * save a bean or a composite of beans to an XML file. * * @param rootBean * the bean or root bean of the composite */ public void saveBean(final RapidBean rootBean, final URL url, final String encoding) { if (url == null) { throw new IllegalArgumentException("no URL given"); } OutputStreamWriter osw = null; String enc = encoding; try { if (enc == null || enc.length() == 0) { enc = "UTF-8"; } if (url.getProtocol().equals("file")) { final File file = new File(url.getFile().replaceAll("%20", " ")); if (!(file.getParentFile().exists())) { FileHelper.mkdirs(file.getParentFile()); } if (!(file.exists())) { if (!file.createNewFile()) { throw new RapidBeansRuntimeException("Could not create file \"" + file.getAbsolutePath() + "\""); } } osw = new OutputStreamWriter(new FileOutputStream(file), enc); } else if (url.getProtocol().equals("ftp") || url.getProtocol().equals("http")) { final URLConnection urlc = url.openConnection(); if (url.getProtocol().equals("http")) { urlc.setDoOutput(true); } final OutputStream os = urlc.getOutputStream(); osw = new OutputStreamWriter(os, enc); } else { throw new RapidBeansRuntimeException("Unsupported protocol \"" + url.getProtocol() + "\""); } writeToWriter(rootBean, osw, enc); } catch (IOException e) { throw new RapidBeansRuntimeException("writing document file \"" + url.toString() + "\"failed", e); } finally { if (osw != null) { try { osw.close(); } catch (IOException e) { throw new RapidBeansRuntimeException("writing document file \"" + url.toString() + "\"failed", e); } } } } /** * save a bean or a composite of beans to an XML file. * * @param rootBean * the bean or root bean of the composite */ public void writeToWriter(final RapidBean rootBean, Writer osw, String encoding) throws IOException { osw.write("<?xml version=\"1.0\" encoding=\"" + encoding + "\" standalone=\"yes\"?>"); osw.write(LF); this.write(osw, 0, null, rootBean); } /** * save a bean or a composite of beans to an XML string. * * @param rootBean * the bean or root bean of the composite */ public String toString(final RapidBean rootBean, String encoding) { StringWriter sw = new StringWriter(); try { writeToWriter(rootBean, sw, encoding); } catch (IOException e) { // This should not happen as we are writing into memory throw new RapidBeansRuntimeException("Should not happen!", e); } return sw.toString(); } /** * the line feed character sequence. */ private static final String LF = PlatformHelper.getLineFeed(); /** * the bean processor. * * @param osw * the OutputStreamWriter * @param depth * the depth * @param colProp * the parent collection property * @param bean * the bean */ private void write(final Writer osw, final int depth, final PropertyCollection colProp, final RapidBean bean) { try { PlatformHelper.getLineFeed(); String propname = null; String xmlelement = null; if (colProp != null) { propname = colProp.getType().getPropName(); int maxmult = ((TypePropertyCollection) colProp.getType()).getMaxmult(); if ((maxmult > 1 || maxmult < 0) && propname.endsWith("s")) { propname = propname.substring(0, propname.length() - 1); } xmlelement = colProp.getType().mapTypeToXmlElement(bean.getType()); } if (depth == 0) { osw.write("<"); if (bean.getType().getXmlRootElement() != null) { osw.write(bean.getType().getXmlRootElement()); } else { osw.write("rb:bean xmlns:rb=\"http://rapidbeans.org/core/basic\""); osw.write(LF); osw.write("\trb:type=\""); osw.write(bean.getType().getName()); osw.write("\""); } osw.write(LF); } else { for (int i = 0; i < depth; i++) { osw.write("\t"); } osw.write("<"); if (xmlelement != null) { osw.write(xmlelement); } else { osw.write(propname); } osw.write(LF); } if (bean.getType().getIdtype() != IdType.transientid) { for (int i = -1; i < depth; i++) { osw.write("\t"); } osw.write("id=\""); osw.write(bean.getIdString()); osw.write("\""); osw.write(LF); } final List<PropertyCollection> compColProperties = bean.getColPropertiesComposition(); boolean closeImmediately = true; TypeProperty proptype; RapidBean colBean; Collection<?> col; if (colProp != null && ((TypePropertyCollection) colProp.getType()).getTargetType() != bean.getType() && xmlelement == null) { for (int i = -1; i < depth; i++) { osw.write("\t"); } osw.write("rb:type=\""); osw.write(bean.getType().getName()); osw.write("\""); osw.write(LF); } for (Property prop : bean.getPropertyList()) { proptype = prop.getType(); if (proptype.isTransient()) { continue; } if (prop.getValue() != null && (!(proptype instanceof TypePropertyCollection) || (!((TypePropertyCollection) proptype) .isComposition()))) { switch (proptype.getXmlBindingType()) { case attribute: for (int i = -1; i < depth; i++) { osw.write("\t"); } osw.write(prop.getType().getPropName()); osw.write("=\""); osw.write(prop.toString()); osw.write("\""); osw.write(LF); break; case element: closeImmediately = false; break; } } } for (int i = -1; i < depth; i++) { osw.write("\t"); } if (closeImmediately) { for (PropertyCollection prop : compColProperties) { if (prop.getValue() != null && ((Collection<?>) prop.getValue()).size() > 0) { closeImmediately = false; break; } } } if (closeImmediately && depth > 0) { osw.write("/>"); osw.write(LF); } else { osw.write(">"); osw.write(LF); for (PropertyCollection prop : compColProperties) { col = (Collection<?>) prop.getValue(); if (col == null) { continue; } for (Object o : (Collection<?>) prop.getValue()) { colBean = (RapidBean) o; this.write(osw, depth + 1, prop, colBean); } } } for (Property prop : bean.getPropertyList()) { proptype = prop.getType(); if (proptype.isTransient()) { continue; } if (prop.getValue() != null && (!(proptype instanceof TypePropertyCollection) || (!((TypePropertyCollection) proptype) .isComposition()))) { switch (proptype.getXmlBindingType()) { case element: for (int i = -1; i < depth; i++) { osw.write("\t"); } osw.write("<"); osw.write(prop.getType().getPropName()); osw.write(">"); osw.write(prop.toString()); osw.write("</"); osw.write(prop.getType().getPropName()); osw.write(">"); osw.write(LF); break; case attribute: break; } } } if (depth == 0) { osw.write("</"); if (bean.getType().getXmlRootElement() != null) { osw.write(bean.getType().getXmlRootElement()); } else { osw.write("rb:bean"); } osw.write(">"); osw.write(LF); } else { if (!closeImmediately) { for (int i = 0; i < depth; i++) { osw.write("\t"); } osw.write("</"); if (xmlelement != null) { osw.write(xmlelement); } else { osw.write(propname); } osw.write(">"); osw.write(LF); } } } catch (IOException e) { throw new RapidBeansRuntimeException("writing document file failed", e); } } }