/*
* Copyright 2003, 2004 The Apache Software Foundation
*
* Licensed 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 org.apache.ws.jaxme.impl;
import javax.xml.bind.DatatypeConverterInterface;
import javax.xml.bind.JAXBException;
import javax.xml.namespace.QName;
import org.apache.ws.jaxme.JMMarshaller;
import org.apache.ws.jaxme.JMXmlSerializer;
import org.apache.ws.jaxme.XMLConstants;
import org.apache.ws.jaxme.util.NamespaceSupport;
import org.xml.sax.Attributes;
import org.xml.sax.ContentHandler;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.AttributesImpl;
/**
* @author <a href="mailto:joe@ispsoft.de">Jochen Wiedmann</a>
* @version $Id: JMXmlSerializerImpl.java,v 1.3.2.3 2004/09/02 10:31:50 jochen Exp $
*/
public class JMXmlSerializerImpl implements JMXmlSerializer {
private static final Attributes zeroAttributes = new AttributesImpl();
protected class Data implements JMXmlSerializer.Data {
private boolean rootElementCreated;
private int cnt;
private JMMarshaller marshaller;
private ContentHandler handler;
private NamespaceSupport nss = new NamespaceSupport();
protected Data(JMMarshaller pMarshaller, ContentHandler pHandler) {
marshaller = pMarshaller;
handler = pHandler;
}
public JMMarshaller getJMMarshaller() { return marshaller; }
public ContentHandler getContentHandler() { return handler; }
public NamespaceSupport getNamespaceContext() { return nss; }
public DatatypeConverterInterface getDatatypeConverter() { return getJMMarshaller().getDatatypeConverter(); }
public JMXmlSerializer getJMXmlSerializer() {
return JMXmlSerializerImpl.this;
}
public String getNewPrefix(String pURI, String pSuggestedPrefix) {
if (pSuggestedPrefix == null || pSuggestedPrefix.length() == 0) {
if (!nss.isPrefixDeclared("")) {
nss.declarePrefix("", pURI);
return "";
}
pSuggestedPrefix = "p";
}
String pc = pSuggestedPrefix;
for (;;) {
if (!nss.isPrefixDeclared(pc)) {
nss.declarePrefix(pc, pURI);
return pc;
}
pc = pSuggestedPrefix + ++cnt;
}
}
public boolean isRootElementCreated() { return rootElementCreated; }
public void setRootElementCreated(boolean pCreated) {
rootElementCreated = pCreated;
}
}
private JAXBContextImpl factory;
public void init(JAXBContextImpl pFactory) throws JAXBException {
factory = pFactory;
}
public JAXBContextImpl getFactory() {
return factory;
}
public String getPreferredPrefix(String pURI) {
return null;
}
public JMXmlSerializer.Data getData(JMMarshaller pMarshaller, ContentHandler pHandler) {
return new Data(pMarshaller, pHandler);
}
protected AttributesImpl getAttributes(JMXmlSerializer.Data pData,
Object pElement) throws SAXException {
return new AttributesImpl();
}
protected String getAttributeQName(JMXmlSerializer.Data pData, String pURI, String pLocalName)
throws SAXException {
NamespaceSupport nss = pData.getNamespaceContext();
String prefix = nss.getAttributePrefix(pURI);
if (prefix == null) {
String preferredPrefix = getPreferredPrefix(pURI);
if (preferredPrefix == null || preferredPrefix.length() == 0) {
preferredPrefix = "p";
}
prefix = pData.getNewPrefix(pURI, preferredPrefix);
pData.getContentHandler().startPrefixMapping(prefix, pURI);
}
if (prefix.length() == 0) {
return pLocalName;
} else {
return prefix + ":" + pLocalName;
}
}
protected String getElementQName(JMXmlSerializer.Data pData, String pURI,
String pLocalName) throws SAXException {
NamespaceSupport nss = pData.getNamespaceContext();
String prefix = nss.getPrefix(pURI);
if (prefix == null) {
prefix = pData.getNewPrefix(pURI, getPreferredPrefix(pURI));
pData.getContentHandler().startPrefixMapping(prefix, pURI);
}
if (prefix.length() == 0) {
return pLocalName;
} else {
return prefix + ":" + pLocalName;
}
}
protected void marshalChilds(JMXmlSerializer.Data pData, Object pElement)
throws SAXException {
}
protected void marshalAtomicChild(JMXmlSerializer.Data pData,
QName pQName,
String pValue)
throws SAXException {
ContentHandler handler = pData.getContentHandler();
String uri = pQName.getNamespaceURI();
String localName = pQName.getLocalPart();
String qName = getElementQName(pData, uri, localName);
handler.startElement(uri, localName, qName, zeroAttributes);
if (pValue.length() > 0) {
handler.characters(pValue.toCharArray(), 0, pValue.length());
}
handler.endElement(uri, localName, qName);
}
protected void marshalAtomicChild(JMXmlSerializer.Data pData,
String pNamespaceURI,
String pLocalName,
String pValue)
throws SAXException {
ContentHandler handler = pData.getContentHandler();
String qName = getElementQName(pData, pNamespaceURI, pLocalName);
handler.startElement(pNamespaceURI, pLocalName, qName, zeroAttributes);
handler.characters(pValue.toCharArray(), 0, pValue.length());
handler.endElement(pNamespaceURI, pLocalName, qName);
}
public void marshal(JMXmlSerializer.Data pData, QName pName, Object pElement)
throws SAXException {
NamespaceSupport nss = pData.getNamespaceContext();
int context = nss.getContext();
ContentHandler handler = pData.getContentHandler();
String uri = pName.getNamespaceURI();
if (uri == null) uri = "";
String name = pName.getLocalPart();
String qName = getElementQName(pData, uri, name);
AttributesImpl attrs = getAttributes(pData, pElement);
if (!pData.isRootElementCreated()) {
createSchemaLocationAttributes(pData, attrs);
pData.setRootElementCreated(true);
}
handler.startElement(uri, name, qName, attrs);
marshalChilds(pData, pElement);
handler.endElement(uri, name, qName);
for (;;) {
String prefix = nss.setContext(context);
if (prefix == null) {
break;
}
handler.endPrefixMapping(prefix);
}
}
protected void createSchemaLocationAttributes(JMXmlSerializer.Data pData, AttributesImpl pAttrs) throws SAXException {
JMMarshallerImpl m = (JMMarshallerImpl) pData.getJMMarshaller();
String schemaLocation = m.getSchemaLocation();
String schemaLocationAttribute;
if (schemaLocation != null) {
schemaLocationAttribute = XMLConstants.XML_SCHEMA_NS_ATTR;
} else {
schemaLocation = m.getNoNamespaceSchemaLocation();
if (schemaLocation != null) {
schemaLocationAttribute = XMLConstants.XML_SCHEMA_NO_NS_ATTR;
} else {
schemaLocationAttribute = null;
}
}
if (schemaLocation != null) {
NamespaceSupport nss = pData.getNamespaceContext();
String xsi = nss.getPrefix(XMLConstants.XML_SCHEMA_URI);
if (xsi == null) {
xsi = pData.getNewPrefix(XMLConstants.XML_SCHEMA_URI, "xsi");
pData.getContentHandler().startPrefixMapping(xsi, XMLConstants.XML_SCHEMA_URI);
}
String xsiQName = (xsi == null || "".equals(xsi)) ?
schemaLocationAttribute : (xsi + ":" + schemaLocationAttribute);
pAttrs.addAttribute(XMLConstants.XML_SCHEMA_URI, schemaLocationAttribute, xsiQName, "CDATA",
schemaLocation);
}
}
}