/* * Copyright (C) 2005-2012 BetaCONCEPT Limited * * This file is part of Astroboa. * * Astroboa 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. * * Astroboa 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 copy of the GNU Lesser General Public License * along with Astroboa. If not, see <http://www.gnu.org/licenses/>. */ package org.betaconceptframework.astroboa.model.jaxb; import java.io.File; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.Writer; import java.nio.charset.Charset; import java.util.List; import javax.xml.bind.JAXBException; import javax.xml.bind.Marshaller; import javax.xml.bind.PropertyException; import javax.xml.bind.ValidationEventHandler; import javax.xml.bind.annotation.adapters.XmlAdapter; import javax.xml.bind.attachment.AttachmentMarshaller; import javax.xml.stream.XMLEventWriter; import javax.xml.stream.XMLStreamWriter; import javax.xml.transform.Result; import javax.xml.validation.Schema; import org.apache.commons.lang.BooleanUtils; import org.apache.commons.lang.StringUtils; import org.betaconceptframework.astroboa.api.model.exception.CmsException; import org.betaconceptframework.astroboa.api.model.io.ResourceRepresentationType; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.w3c.dom.Node; import org.xml.sax.ContentHandler; /** * This is a wrapper of a JAXB Marshaller. * * It keeps several properties which are used during marshalling Astroboa Entities. * * * @author Gregory Chomatas (gchomatas@betaconcept.com) * @author Savvas Triantafyllou (striantafyllou@betaconcept.com) * */ public class AstroboaMarshaller implements Marshaller{ private Marshaller marshaller; private final Logger logger = LoggerFactory.getLogger(getClass()); /** * This property represents all property paths that will be marshaled * in cases where marshaling entire content object is not desired */ public final static String CMS_PROPERTIES_TO_BE_MARSHALLED = "cmsPropertiesToBeMarshalled"; /** * Object holding all property paths which should be marshaled */ private List<String> cmsPropertiesToBeMarshalled; private ResourceRepresentationType<?> resourceRepresentationType; public AstroboaMarshaller(Marshaller marshaller, ResourceRepresentationType<?> resourceRepresentationType) { this.marshaller = marshaller; this.resourceRepresentationType = resourceRepresentationType; if (marshaller == null){ throw new CmsException("No marshaller provided. Cannot instantiate Astroboa Marshaller"); } } @Override public <A extends XmlAdapter> A getAdapter(Class<A> arg0) { return marshaller.getAdapter(arg0); } @Override public AttachmentMarshaller getAttachmentMarshaller() { return marshaller.getAttachmentMarshaller(); } @Override public ValidationEventHandler getEventHandler() throws JAXBException { return marshaller.getEventHandler(); } @Override public Listener getListener() { return marshaller.getListener(); } @Override public Node getNode(Object arg0) throws JAXBException { return marshaller.getNode(arg0); } @Override public Object getProperty(String arg0) throws PropertyException { if (StringUtils.isBlank(arg0)){ return null; } if (CMS_PROPERTIES_TO_BE_MARSHALLED.equals(arg0)){ return cmsPropertiesToBeMarshalled; } return marshaller.getProperty(arg0); } @Override public Schema getSchema() { return marshaller.getSchema(); } public boolean outputTypeIsJSON() { return resourceRepresentationType != null && resourceRepresentationType != ResourceRepresentationType.XML ; } @Override public void marshal(Object arg0, Result arg1) throws JAXBException { marshaller.marshal(arg0, arg1); } @Override public void marshal(Object arg0, OutputStream arg1) throws JAXBException { if (outputTypeIsJSON()){ marshaller.marshal(arg0, new OutputStreamWriter(arg1, Charset.forName("UTF-8"))); } else{ marshaller.marshal(arg0, arg1); } } @Override public void marshal(Object arg0, Writer arg1) throws JAXBException { if (outputTypeIsJSON()){ XMLStreamWriter jsonXmlStreamWriter = null; try { jsonXmlStreamWriter = CmsEntitySerialization.Context.createJsonXmlStreamWriter(arg1, true,BooleanUtils.isTrue((Boolean)marshaller.getProperty(Marshaller.JAXB_FORMATTED_OUTPUT))); marshal(arg0, jsonXmlStreamWriter ); } catch (Exception e) { try{ if (jsonXmlStreamWriter != null){ jsonXmlStreamWriter.flush(); logger.error("JSON Export so far {}", arg1); } } catch(Exception e1){ //Ignore it } throw new JAXBException(e); } } else{ marshaller.marshal(arg0, arg1); } } @Override public void marshal(Object arg0, ContentHandler arg1) throws JAXBException { marshaller.marshal(arg0, arg1); } @Override public void marshal(Object arg0, Node arg1) throws JAXBException { marshaller.marshal(arg0, arg1); } @Override public void marshal(Object arg0, XMLStreamWriter arg1) throws JAXBException { marshaller.marshal(arg0, arg1); } @Override public void marshal(Object arg0, XMLEventWriter arg1) throws JAXBException { marshaller.marshal(arg0, arg1); } @Override public void setAdapter(XmlAdapter arg0) { marshaller.setAdapter(arg0); } @Override public <A extends XmlAdapter> void setAdapter(Class<A> arg0, A arg1) { marshaller.setAdapter(arg0, arg1); } @Override public void setAttachmentMarshaller(AttachmentMarshaller arg0) { marshaller.setAttachmentMarshaller(arg0); } @Override public void setEventHandler(ValidationEventHandler arg0) throws JAXBException { marshaller.setEventHandler(arg0); } @Override public void setListener(Listener arg0) { marshaller.setListener(arg0); } @Override public void setProperty(String arg0, Object arg1) throws PropertyException { if (StringUtils.isNotBlank(arg0)){ if (CMS_PROPERTIES_TO_BE_MARSHALLED.equals(arg0)){ if (! (arg1 instanceof List) ){ throw new PropertyException("Marshaller property "+CMS_PROPERTIES_TO_BE_MARSHALLED+ " must be of type List<String>"); } cmsPropertiesToBeMarshalled = (List<String>) arg1; } else if (Marshaller.JAXB_SCHEMA_LOCATION.equals(arg0) && outputTypeIsJSON()) { //Do not provide schema location when marshaling to JSON } else { marshaller.setProperty(arg0, arg1); } } } @Override public void setSchema(Schema arg0) { marshaller.setSchema(arg0); } @Override public void marshal(Object jaxbElement, File output) throws JAXBException { marshaller.marshal(jaxbElement, output); } }