package org.juxtasoftware.service.importer;
import java.io.IOException;
import org.apache.commons.io.IOUtils;
import org.juxtasoftware.dao.JuxtaXsltDao;
import org.juxtasoftware.model.JuxtaXslt;
import org.juxtasoftware.service.importer.XmlTemplateParser.TemplateInfo;
import org.juxtasoftware.util.NamespaceExtractor.NamespaceInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
/**
* Factory for creating JuxtaXslt instances
* @author loufoster
*/
@Component
@Scope(BeanDefinition.SCOPE_SINGLETON)
public final class JuxtaXsltFactory {
@Autowired private JuxtaXsltDao xsltDao;
private static final String BASIC_XSLT = "xslt/basic-strip-ws.xslt";
private static final String SINGLE_XSLT = "xslt/single-exclusion.xslt";
private static final String GLOBAL_XSLT = "xslt/global-exclusion.xslt";
private static final String BREAKS_XSLT = "xslt/breaks.xslt";
/**
* Get the generic XSLT template as a string
* @return
* @throws IOException
*/
public static String getGenericTemplate() throws IOException {
return IOUtils.toString( ClassLoader.getSystemResourceAsStream(BASIC_XSLT), "utf-8");
}
/**
* Get the single exclusion XSLT template fragment as a string
* @return
* @throws IOException
*/
public static String getSingleExclusionTemplate() throws IOException {
return IOUtils.toString( ClassLoader.getSystemResourceAsStream(SINGLE_XSLT), "utf-8");
}
/**
* Get the global exclusion XSLT template fragment as a string
* @return
* @throws IOException
*/
public static String getGlobalExclusionTemplate() throws IOException {
return IOUtils.toString( ClassLoader.getSystemResourceAsStream(GLOBAL_XSLT), "utf-8");
}
/**
* Get the linebreaks XSLT fragment as a string
* @return
* @throws IOException
*/
public static String getBreaksTemplate() throws IOException {
return IOUtils.toString( ClassLoader.getSystemResourceAsStream(BREAKS_XSLT), "utf-8");
}
public JuxtaXslt create( final Long workspaceId, final String name ) throws IOException {
String xslt = JuxtaXsltFactory.getGenericTemplate();
xslt = xslt.replaceAll("\\{LINEBREAK\\}", "
");
// for this generic template, no tags are referred to directly (just *),
// so no namespace info is needed.
xslt = xslt.replaceAll("\\{NAMESPACE\\}", "");
// Wildcard notes and pb tags so they always get the specialized tag handling
xslt = xslt.replaceAll("\\{NOTE\\}", wildCardNamespace("note"));
xslt = xslt.replaceAll("\\{PB\\}", wildCardNamespace("pb"));
String breaksXslt = JuxtaXsltFactory.getBreaksTemplate();
breaksXslt = breaksXslt.replaceAll("\\{LB_LIST\\}", "*");
int breakPos = xslt.indexOf("<!--breaks-->")+13;
xslt = xslt.substring(0, breakPos)+"\n "+breaksXslt+xslt.substring(breakPos);
JuxtaXslt jxXslt = new JuxtaXslt();
jxXslt.setName(name+"-transform-"+System.currentTimeMillis());
jxXslt.setWorkspaceId( workspaceId );
jxXslt.setXslt(xslt);
Long id = this.xsltDao.create(jxXslt);
jxXslt.setId(id);
return jxXslt;
}
/**
* Create a new instance of a JuxtaXslt based on setings extracted from a desktop-derived template XML file
* Note that these types of files
*
* @param workspaceId
* @param name
* @param info
* @return
* @throws IOException
*/
public JuxtaXslt createFromTemplateInfo(final Long workspaceId, final String name, final TemplateInfo info, final NamespaceInfo namespace ) throws IOException {
JuxtaXslt jxXslt = new JuxtaXslt();
jxXslt.setName(name+"-transform-"+System.currentTimeMillis());
jxXslt.setWorkspaceId( workspaceId );
String xslt = JuxtaXsltFactory.getGenericTemplate();
// stuff the correct namespace info in the declaration and setup
// special note/pb handling
if ( namespace.hasNoPrefix() ) {
xslt = xslt.replaceAll("\\{NAMESPACE\\}", "");
xslt = xslt.replaceAll("\\{NOTE\\}", "note" );
xslt = xslt.replaceAll("\\{PB\\}", "pb" );
} else {
xslt = xslt.replaceAll("\\{NAMESPACE\\}", namespace.toString());
xslt = xslt.replaceAll("\\{NOTE\\}", namespace.getPrefix()+":note" );
xslt = xslt.replaceAll("\\{PB\\}", namespace.getPrefix()+":pb" );
}
// for serverside transforms, the linefeed can be an actual linefeed char
xslt = xslt.replaceAll("\\{LINEBREAK\\}", "
");
// get the template exclusion / linebreak info and insert to XSLT
if ( info.getLineBreaks().size() > 0 ) {
StringBuilder lb = new StringBuilder();
for ( String tag : info.getLineBreaks() ) {
if ( lb.length() > 0 ) {
lb.append("|");
}
lb.append( namespace.addNamespacePrefix(tag) );
}
String breaksXslt = IOUtils.toString( ClassLoader.getSystemResourceAsStream("xslt/breaks.xslt"), "utf-8");
breaksXslt = breaksXslt.replaceAll("\\{LB_LIST\\}", lb.toString());
int breakPos = xslt.indexOf("<!--breaks-->")+13;
xslt = xslt.substring(0, breakPos)+"\n "+breaksXslt+xslt.substring(breakPos);
}
// all desktop excludes are global excludes. Add them to the xslt
StringBuilder excludes = new StringBuilder();
for ( String tag : info.getExcludes() ) {
excludes.append("\n <xsl:template match=\"");
excludes.append( namespace.addNamespacePrefix(tag) ).append("\"/>");
}
final String key = "<!--global-exclusions-->";
int pos = xslt.indexOf(key)+key.length();
xslt = xslt.substring(0, pos) + excludes.toString() + xslt.substring(pos);
if ( namespace.isDefault() ) {
jxXslt.setDefaultNamespace(namespace.getPrefix());
}
jxXslt.setXslt(xslt);
Long id = this.xsltDao.create(jxXslt);
jxXslt.setId(id);
return jxXslt;
}
private String wildCardNamespace( final String tag ) {
return "*[local-name()='"+tag+"']";
}
}