/*
* Copyright 2004-2009 the original author or authors.
*
* 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.compass.core.xml.javax.converter;
import java.io.Reader;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.compass.core.CompassException;
import org.compass.core.config.CompassConfigurable;
import org.compass.core.config.CompassEnvironment;
import org.compass.core.config.CompassSettings;
import org.compass.core.config.ConfigurationException;
import org.compass.core.converter.ConversionException;
import org.compass.core.converter.xsem.SupportsXmlContentWrapper;
import org.compass.core.converter.xsem.XmlContentConverter;
import org.compass.core.util.StringBuilderWriter;
import org.compass.core.xml.AliasedXmlObject;
import org.compass.core.xml.XmlObject;
import org.compass.core.xml.javax.NodeAliasedXmlObject;
import org.compass.core.xml.javax.NodeXmlObject;
import org.w3c.dom.Document;
import org.xml.sax.InputSource;
/**
* <p>Uses JSE to convert an xml content to and from {@link NodeAliasedXmlObject}.
*
* @author kimchy
*/
public class NodeXmlContentConverter implements XmlContentConverter, CompassConfigurable, SupportsXmlContentWrapper {
private static Log log = LogFactory.getLog(NodeXmlContentConverter.class);
protected DocumentBuilder documentBuilder;
protected Transformer transformer;
public void configure(CompassSettings settings) throws CompassException {
try {
this.documentBuilder = doCreateDocumentBuilder(settings);
} catch (ParserConfigurationException e) {
throw new ConfigurationException("Failed to create document builder", e);
}
if (log.isDebugEnabled()) {
log.debug("Using document builder [" + documentBuilder.getClass().getName() + "]");
}
try {
this.transformer = doCreateTransformer(settings);
} catch (TransformerConfigurationException e) {
throw new ConfigurationException("Failed to create transformer", e);
}
if (log.isDebugEnabled()) {
log.debug("Using transformer [" + transformer.getClass().getName() + "]");
}
}
/**
* An extension point allowing to control how a {@link javax.xml.parsers.DocumentBuilder} is
* created. By default uses <code>DocumentBuilderFactory.newInstance().newDocumentBuilder()</code>.
*/
protected DocumentBuilder doCreateDocumentBuilder(CompassSettings settings) throws ParserConfigurationException {
return DocumentBuilderFactory.newInstance().newDocumentBuilder();
}
/**
* An extension point allowing to control how a {@link javax.xml.transform.Transformer} is
* created. By default uses <code>TransformerFactory.newInstance().newTransformer()</code>.
*/
protected Transformer doCreateTransformer(CompassSettings settings) throws TransformerConfigurationException {
return TransformerFactory.newInstance().newTransformer();
}
/**
* This converter does not support a singleton wrapper strategy.
*/
public boolean supports(String wrapper) {
return !CompassEnvironment.Xsem.XmlContent.WRAPPER_SINGLETON.equals(wrapper);
}
/**
* Uses the already created {@link javax.xml.parsers.DocumentBuilder}
* and parse the given xml into a {@link NodeAliasedXmlObject}.
*
* @param alias The alias that will be associated with the {@link NodeAliasedXmlObject}
* @param xml The xml string to parse into {@link NodeAliasedXmlObject}
* @return A {@link NodeAliasedXmlObject} parsed from the given xml string and associated with the given alias
* @throws ConversionException In case the xml parsing failed
*/
public AliasedXmlObject fromXml(String alias, Reader xml) throws ConversionException {
Document document;
try {
document = documentBuilder.parse(new InputSource(xml));
} catch (Exception e) {
throw new ConversionException("Failed to parse alias[" + alias + "] xml[" + xml + "]", e);
}
return new NodeAliasedXmlObject(alias, document);
}
/**
* Converts a {@link NodeXmlObject} into an xml string.
* Uses the created {@link javax.xml.transform.Transformer} to do it.
*
* @param xmlObject The {@link NodeXmlObject} to convert into an xml string
* @return The xml string representation of the given {@link NodeXmlObject}
* @throws ConversionException Should not really happen...
*/
public String toXml(XmlObject xmlObject) throws ConversionException {
NodeXmlObject nodeXmlObject = (NodeXmlObject) xmlObject;
Source source = new DOMSource(nodeXmlObject.getNode());
StringBuilderWriter sw = StringBuilderWriter.Cached.cached();
Result result = new StreamResult(sw);
try {
transformer.transform(source, result);
} catch (Exception e) {
throw new ConversionException("Failed to marshall to xml, this should not happen", e);
}
return sw.toString();
}
}