/*
* Copyright 2015-Present Entando Inc. (http://www.entando.com) All rights reserved.
*
* This library 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 2.1 of the License, or (at your option)
* any later version.
*
* This library 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.
*/
package org.entando.entando.aps.system.services.api.provider.json;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.nio.charset.Charset;
import java.util.LinkedList;
import java.util.List;
import javax.xml.namespace.QName;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamWriter;
import org.apache.cxf.common.util.StringUtils;
import org.apache.cxf.staxutils.DelegatingXMLStreamWriter;
import org.codehaus.jettison.AbstractXMLStreamWriter;
import org.codehaus.jettison.mapped.Configuration;
import org.codehaus.jettison.mapped.MappedNamespaceConvention;
import org.entando.entando.aps.system.services.api.model.CDataAdapter;
/**
* @author E.Santoboni
*/
public class ApsJSONUtils {
private static final Charset UTF8 = Charset.forName("utf-8");
public static XMLStreamWriter createIgnoreMixedContentWriterIfNeeded(XMLStreamWriter writer, boolean ignoreMixedContent) {
return ignoreMixedContent ? new IgnoreMixedContentWriter(writer) : writer;
}
public static XMLStreamWriter createIgnoreNsWriterIfNeeded(XMLStreamWriter writer,
boolean ignoreNamespaces,
boolean ignoreXsiAttributes) {
return ignoreNamespaces ? new CDataIgnoreNamespacesWriter(writer, ignoreXsiAttributes) : writer;
}
public static XMLStreamWriter createStreamWriter(OutputStream os,
QName qname, boolean writeXsiType, Configuration config,
boolean serializeAsArray, List<String> arrayKeys,
boolean dropRootElement, String enc) throws Exception {
MappedNamespaceConvention convention = new MappedNamespaceConvention(config);
AbstractXMLStreamWriter xsw = new CDataMappedXMLStreamWriter(convention, new OutputStreamWriter(os, enc));
if (serializeAsArray) {
if (arrayKeys != null) {
for (String key : arrayKeys) {
xsw.serializeAsArray(key);
}
} else if (qname != null) {
String key = getKey(convention, qname);
xsw.serializeAsArray(key);
}
}
XMLStreamWriter writer = !writeXsiType || dropRootElement
? new IgnoreContentJettisonWriter(xsw, writeXsiType, dropRootElement) : xsw;
return writer;
}
private static String getKey(MappedNamespaceConvention convention, QName qname) throws Exception {
return convention.createKey(qname.getPrefix(),
qname.getNamespaceURI(), qname.getLocalPart());
}
private static class IgnoreMixedContentWriter extends DelegatingXMLStreamWriter {
String lastText;
boolean isMixed;
List<Boolean> mixed = new LinkedList<Boolean>();
public IgnoreMixedContentWriter(XMLStreamWriter writer) {
super(writer);
}
@Override
public void writeCharacters(String text) throws XMLStreamException {
if (CDataAdapter.isCdata(new String(text))) {
text = CDataAdapter.parse(new String(text));
}
if (StringUtils.isEmpty(text.trim())) {
lastText = text;
} else if (lastText != null) {
lastText += text;
} else if (!isMixed) {
super.writeCharacters(text);
} else {
lastText = text;
}
}
@Override
public void writeStartElement(String prefix, String local, String uri) throws XMLStreamException {
if (lastText != null) {
isMixed = true;
}
mixed.add(0, isMixed);
lastText = null;
isMixed = false;
super.writeStartElement(prefix, local, uri);
}
@Override
public void writeStartElement(String uri, String local) throws XMLStreamException {
if (lastText != null) {
isMixed = true;
}
mixed.add(0, isMixed);
lastText = null;
isMixed = false;
super.writeStartElement(uri, local);
}
@Override
public void writeStartElement(String local) throws XMLStreamException {
if (lastText != null) {
isMixed = true;
}
mixed.add(0, isMixed);
lastText = null;
isMixed = false;
super.writeStartElement(local);
}
@Override
public void writeEndElement() throws XMLStreamException {
if (lastText != null && (!isMixed || !StringUtils.isEmpty(lastText.trim()))) {
super.writeCharacters(lastText.trim());
}
super.writeEndElement();
isMixed = mixed.get(0);
mixed.remove(0);
}
}
private static class IgnoreContentJettisonWriter extends DelegatingXMLStreamWriter {
private boolean writeXsiType;
private boolean dropRootElement;
private boolean rootDropped;
private int index;
public IgnoreContentJettisonWriter(XMLStreamWriter writer, boolean writeXsiType, boolean dropRootElement) {
super(writer);
this.writeXsiType = writeXsiType;
this.dropRootElement = dropRootElement;
}
@Override
public void writeAttribute(String prefix, String uri,
String local, String value) throws XMLStreamException {
if (!writeXsiType && "xsi".equals(prefix)
&& ("type".equals(local) || "nil".equals(local))) {
return;
}
super.writeAttribute(prefix, uri, local, value);
}
@Override
public void writeStartElement(String prefix, String local, String uri) throws XMLStreamException {
index++;
if (dropRootElement && index - 1 == 0) {
rootDropped = true;
return;
}
super.writeStartElement(prefix, local, uri);
}
@Override
public void writeStartElement(String local) throws XMLStreamException {
this.writeStartElement("", local, "");
}
@Override
public void writeEndElement() throws XMLStreamException {
index--;
if (rootDropped && index == 0) {
return;
}
super.writeEndElement();
}
@Override
public void writeCharacters(String text) throws XMLStreamException {
if (CDataAdapter.isCdata(new String(text))) {
String parsedCDataText = CDataAdapter.parse(new String(text));
super.writeCharacters(parsedCDataText);
} else {
super.writeCharacters(text);
}
}
}
}