XslTransformer.java
package org.andromda.core.transformation;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.net.URL;
import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.URIResolver;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
import org.andromda.core.common.AndroMDALogger;
import org.andromda.core.common.ResourceUtils;
import org.andromda.core.configuration.Transformation;
import org.apache.commons.lang.StringUtils;
/**
* An implementation of Transformer that provides
* XSLT transformations. The {@link #transform(String, Transformation[])}
* operation will apply the given XSLT files to the model
* in the order which they are found.
*
* @author Chad Brandon
*/
public class XslTransformer
implements Transformer
{
/**
* Applies the given XSLT files to the model in the order in which they are found.
*
* @see org.andromda.core.transformation.Transformer#transform(String, org.andromda.core.configuration.Transformation[])
*/
public InputStream transform(
final String modelUri,
final Transformation[] xsltTransformations)
{
try
{
InputStream stream = null;
if (StringUtils.isNotBlank(modelUri))
{
final URL modelUrl = new URL(modelUri);
if (xsltTransformations != null && xsltTransformations.length > 0)
{
Source modelSource = new StreamSource(modelUrl.openStream());
final Collection<Transformation> xslts = Arrays.asList(xsltTransformations);
final TransformerFactory factory = TransformerFactory.newInstance();
final TransformerURIResolver resolver = new TransformerURIResolver();
factory.setURIResolver(resolver);
for (final Iterator<Transformation> xsltIterator = xslts.iterator(); xsltIterator.hasNext();)
{
final Transformation transformation = xsltIterator.next();
final URL xslt = new URL(transformation.getUri());
resolver.setLocation(xslt);
AndroMDALogger.info("Applying transformation --> '" + xslt + '\'');
final Source xsltSource = new StreamSource(xslt.openStream());
final javax.xml.transform.Transformer transformer = factory.newTransformer(xsltSource);
final ByteArrayOutputStream output = new ByteArrayOutputStream();
final Result result = new StreamResult(output);
transformer.transform(modelSource, result);
final byte[] outputResult = output.toByteArray();
stream = new ByteArrayInputStream(outputResult);
// if we have an output location specified, write the result
final String outputLocation = transformation.getOutputLocation();
if (StringUtils.isNotBlank(outputLocation))
{
final File fileOutput = new File(outputLocation);
final File parent = fileOutput.getParentFile();
if (parent != null)
{
parent.mkdirs();
}
FileOutputStream outputStream = new FileOutputStream(fileOutput);
AndroMDALogger.info("Transformation output: '" + outputLocation + '\'');
outputStream.write(outputResult);
outputStream.flush();
outputStream.close();
}
if (xsltIterator.hasNext())
{
modelSource = new StreamSource(stream);
}
}
}
else
{
stream = modelUrl.openStream();
}
}
return stream;
}
catch (final Exception exception)
{
throw new XslTransformerException(exception);
}
}
/**
* Provides the URI resolving capabilities for the
* {@link XslTransformer}
*/
static final class TransformerURIResolver
implements URIResolver
{
/**
* @see javax.xml.transform.URIResolver#resolve(String, String)
*/
public Source resolve(
final String href,
final String base)
throws TransformerException
{
Source source = null;
if (this.location != null)
{
String locationUri = ResourceUtils.normalizePath(this.location.toString());
locationUri = locationUri.substring(0, locationUri.lastIndexOf('/') + 1);
source = new StreamSource(locationUri + href);
}
return source;
}
/**
* The current transformation location.
*/
private URL location;
/**
* Sets the location of the current transformation.
*
* @param location the transformation location as a URI.
*/
public void setLocation(URL location)
{
this.location = location;
}
}
}