package net.sf.jpluck.jxl;
import java.awt.Color;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.logging.Logger;
import java.util.regex.Pattern;
import javax.xml.transform.Source;
import javax.xml.transform.Templates;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.URIResolver;
import javax.xml.transform.dom.DOMResult;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamSource;
import net.sf.jpluck.util.ColorUtil;
import net.sf.jpluck.xml.ContextAdapter;
import net.sf.jpluck.xml.NamespaceURI;
import org.apache.commons.jxpath.JXPathException;
import org.apache.commons.jxpath.Pointer;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
public class Template extends JXLElement {
public static Logger logger = Logger.getLogger("jxl");
protected JXL jxl;
protected List exclusionPatternList = new ArrayList();
protected Template parent;
protected URIRewriter uriRewriter;
private List pipelineList = new ArrayList();
private String systemId;
public Template(Element element, JXL jxl) {
super(element);
this.jxl = jxl;
for (Iterator it = resolveIteratePointers("exclude/pattern"); it.hasNext();) {
Pointer pointer = (Pointer) it.next();
Pattern pattern = Pattern.compile((String) pointer.getValue());
exclusionPatternList.add(pattern);
}
}
public boolean isAutoDetectInputEncoding() {
return getInputEncoding().equalsIgnoreCase("auto");
}
public String[] getCategories() {
return toStringArray(resolveIterate("category"));
}
public Date getDate() {
try {
return JXL.stringToDate((String) resolveValue("@date"));
} catch (Exception e) {
return null;
}
}
public String getDescription() {
return (String) resolveValue("description");
}
public ImageSettings getEmbeddedImageSettings() {
return getImageSettings("images/embedded");
}
public String getID() {
try {
return (String) getValue("@id");
} catch (JXPathException e) {
return null;
}
}
public boolean isIncludeAltText() {
return ((String) resolveValue("images/@includeAltText", "yes")).equalsIgnoreCase("yes");
}
public boolean isIncludeEmbeddedImages() {
return isIncludeImages(getEmbeddedImageSettings());
}
public boolean isIncludeImageAltText() {
return resolveValue("images/@includeAltText", "yes").equals("yes");
}
public boolean isIncludeStandaloneImages() {
return isIncludeImages(getStandaloneImageSettings());
}
public boolean isIncludeURIInfo() {
return resolveValue("@includeUriInfo", "yes").equals("yes");
}
public String getInputEncoding() {
return (String) resolveValue("@inputEncoding", "auto");
}
public JXL getJXL() {
return jxl;
}
public String getLanguage() {
return (String) resolveValue("@language");
}
public Color getLinkColor() {
String s = (String) resolveValue("@linkColor");
if (s != null) {
return ColorUtil.getColor(s);
} else {
return null;
}
}
public String getOutputEncoding() {
String s = (String) resolveValue("@outputEncoding", "Windows-1252");
if (s.equalsIgnoreCase("PalmLatin")) {
s = "Windows-1252";
}
return s;
}
public String getPrimaryCategory() {
return (String) resolveValue("category[0]");
}
public boolean isRemoveAccents() {
return getValue("@removeAccents", "no").equals("yes");
}
public boolean isRemoveUnresolvedLinks() {
return ((String) resolveValue("@removeUnresolvedLinks", "no")).endsWith("yes");
}
public boolean isSetBackupBit() {
return getValue("@backup", "no").equals("yes");
}
public ImageSettings getStandaloneImageSettings() {
return getImageSettings("images/standalone");
}
public String getTemplateID() {
return (String) getValue("@template", "_default");
}
public int getTextColorBrightness() {
int brightness = 0;
String s = (String) resolveValue("@textColorBrightness");
if (s != null) {
try {
brightness = Integer.parseInt(s);
brightness = ((brightness < -100) ? (-100) : brightness);
brightness = ((brightness > 100) ? 100 : brightness);
} catch (NumberFormatException e) {
}
}
return brightness;
}
public URIRewriter getURIRewriter() {
if (uriRewriter == null) {
uriRewriter = new URIRewriter();
for (Iterator it = resolveIteratePointers("uriRewrite"); it.hasNext();) {
Pointer pointer = (Pointer) it.next();
Element uriRewrite = (Element) pointer.getNode();
uriRewriter.add(Pattern.compile(uriRewrite.getAttribute("pattern")), uriRewrite.getAttribute("value"));
}
}
return uriRewriter;
}
public Color getUnresolvedLinkColor() {
String s = (String) resolveValue("@unresolvedLinkColor");
if (s != null) {
return ColorUtil.getColor(s);
} else {
return null;
}
}
public boolean isUseHiresMargins() {
return ((String) resolveValue("@margins", "standard")).equalsIgnoreCase("hires");
}
public String getUserAgent() {
return (String) getValue("@userAgent");
}
public void configureParentTemplate() {
String template = (String) getValue("@template", "_default");
if (jxl != null) {
parent = jxl.getTemplate(template);
if (parent == this) {
parent = null;
}
}
}
void initTransformationPipelines() throws IOException, TransformerException {
pipelineList.clear();
TransformerFactory tfactory = TransformerFactory.newInstance();
tfactory.setURIResolver(new Resolver());
for (Iterator it = resolveIteratePointers("transform"); it.hasNext();) {
Pointer p = (Pointer) it.next();
Element transformElement = (Element) p.getNode();
ContextAdapter transformContext = new ContextAdapter(transformElement);
List xslList = new ArrayList();
for (Iterator it2 = transformContext.iteratePointers("xslt"); it2.hasNext();) {
Pointer p2 = (Pointer) it2.next();
Element xslElement = (Element) p2.getNode();
Source source;
String href = xslElement.getAttribute("href");
if (href.length() > 0) {
source = new StreamSource(jxl.resolve(href));
} else {
NodeList nodeList = xslElement.getElementsByTagNameNS(NamespaceURI.XSL, "stylesheet");
if (nodeList.getLength() == 1) {
source = new DOMSource((Element) nodeList.item(0));
} else {
throw new RuntimeException("No <xsl:stylesheet> specified inside <xslt> element.");
}
}
Templates templates = tfactory.newTemplates(source);
ContextAdapter xslContext = new ContextAdapter(xslElement);
List parameterList = new ArrayList();
for (Iterator it3 = xslContext.iteratePointers("param"); it3.hasNext();) {
Pointer p3 = (Pointer) it3.next();
Element paramElement = (Element) p3.getNode();
parameterList.add(new Parameter(paramElement.getAttribute("name"),
paramElement.getAttribute("value")));
}
XSL xsl = new XSL(templates, (Parameter[]) parameterList.toArray(new Parameter[parameterList.size()]));
xslList.add(xsl);
}
Pattern pattern = Pattern.compile(transformElement.getAttribute("uriPattern"));
XSL[] xsls = (XSL[]) xslList.toArray(new XSL[xslList.size()]);
TransformationPipeline pipeline = new TransformationPipeline(pattern, xsls);
pipelineList.add(pipeline);
}
}
public boolean shouldExclude(String uri) {
HierarchyTraversal ht = new HierarchyTraversal(this);
return ht.shouldExclude(uri);
}
public org.w3c.dom.Document transform(org.w3c.dom.Document dom, String uri, net.sf.jpluck.plucker.Document pluckerDocument)
throws TransformerException {
for (Iterator it = pipelineList.iterator(); it.hasNext();) {
TransformationPipeline pipeline = (TransformationPipeline) it.next();
if (pipeline.matches(uri)) {
dom = pipeline.transform(dom, uri, pluckerDocument);
break;
}
}
return dom;
}
protected Element resolveElement(String xPath) {
HierarchyTraversal ht = new HierarchyTraversal(this);
return ht.getElement(xPath);
}
protected Iterator resolveIterate(String xPath) {
HierarchyTraversal ht = new HierarchyTraversal(this);
return ht.iterate(xPath);
}
protected Iterator resolveIteratePointers(String xPath) {
HierarchyTraversal ht = new HierarchyTraversal(this);
return ht.iteratePointers(xPath);
}
protected Pointer resolvePointer(String xPath) {
HierarchyTraversal ht = new HierarchyTraversal(this);
return ht.getPointer(xPath);
}
protected Object resolveValue(String xPath) {
HierarchyTraversal ht = new HierarchyTraversal(this);
return ht.getValue(xPath);
}
protected Object resolveValue(String xPath, Object defaultValue) {
HierarchyTraversal ht = new HierarchyTraversal(this);
Object value = ht.getValue(xPath);
if (value != null) {
return value;
} else {
return defaultValue;
}
}
void setSystemId(String systemId) {
this.systemId = systemId;
}
String getSystemId() {
return systemId;
}
private ImageSettings getImageSettings(String xPath) {
Element element = getElement(xPath);
if (element != null) {
return new ImageSettings(element);
} else if (parent != null) {
return parent.getImageSettings(xPath);
} else {
return null;
}
}
private boolean isIncludeImages(ImageSettings imageSettings) {
if (imageSettings != null) {
return imageSettings.getBitDepth() > 0;
} else {
return false;
}
}
private static String[] toStringArray(Iterator it) {
List list = new ArrayList();
while (it.hasNext()) {
String s = (String) it.next();
list.add(s);
}
return (String[]) list.toArray(new String[list.size()]);
}
public boolean isParseTables() {
return resolveValue("@parseTables", "no").equals("yes");
}
private static class Parameter {
private String name;
private String value;
private Parameter(String name, String value) {
this.name = name;
this.value = value;
}
}
private static class Resolver implements URIResolver {
public Source resolve(String href, String base)
throws TransformerException {
try {
File file = new File(base, href);
if (file.exists()) {
return new StreamSource(file);
} else {
// Look in user.home
file = new File(System.getProperty("user.home") + File.separator + "xsl" + File.separator + href);
if (file.exists()) {
return new StreamSource(file);
} else {
// Look in the classpath
URL url = Template.class.getClassLoader().getResource("xsl/" + href);
if (url != null) {
return new StreamSource(url.openStream());
} else {
return null;
}
}
}
} catch (IOException e) {
throw new TransformerException(e);
}
}
}
private class TransformationPipeline {
private Pattern pattern;
private XSL[] xsls;
private TransformationPipeline() {
xsls = new XSL[0];
}
private TransformationPipeline(Pattern pattern, XSL[] xsls) {
this.pattern = pattern;
this.xsls = xsls;
}
private boolean matches(String uri) {
return pattern.matcher(uri).matches();
}
private org.w3c.dom.Document transform(org.w3c.dom.Document document, String uri, net.sf.jpluck.plucker.Document pluckerDocument)
throws TransformerException {
DOMSource source = new DOMSource(document);
for (int i = 0; i < xsls.length; i++) {
XSL xsl = xsls[i];
Transformer transformer = xsl.createTransformer();
transformer.setParameter("uri", uri);
DOMResult result = new DOMResult();
transformer.transform(source, result);
source = new DOMSource(result.getNode());
}
return (org.w3c.dom.Document) source.getNode();
}
}
private static class XSL {
private Templates templates;
private Parameter[] parameters;
private XSL(Templates templates, Parameter[] parameters) {
this.templates = templates;
this.parameters = parameters;
}
private Transformer createTransformer() throws TransformerException {
Transformer transformer = templates.newTransformer();
for (int i = 0; i < parameters.length; i++) {
transformer.setParameter(parameters[i].name, parameters[i].value);
}
return transformer;
}
}
}