Class ZTemplateExtension

java.lang.Object
org.faceless.publisher.ext.ZTemplateExtension
All Implemented Interfaces:
ReportFactoryExtension

public class ZTemplateExtension extends Object

An extension to use the ZTemplate template language as a pre-processor to generate the HTML/XML parsed by BFO Publisher.

This extension is invoked by including a <?ztemplate href="template.ztl"?> processing instruction at the start of the document - the href attribute refers to the template, so the document being parsed is an XML representation of the data.


 <?ztemplate type="text/html" href="test.ztl"?>
 <data header="Colors">
  <items>
   <item first="true"><name>red</name><url>#Red</url></item>
   <item link="true"><name>green</name><url>#Green</url></item>
   <item link="true"><name>blue</name><url>#Blue</url></item>
  </items>
 </data>
 

The processing instruction doesn't have to be added to the XML; it can be added via the API:


 Report report = reportFactory.createReport();
 ProcessingInstruction pi = new ProcessingInstruction().setType("ztemplate").put("href", ""path/to/template.ztl");
 report.getProcessingInstructions().add(pi);
 report.load(new File("data.xml"));
 report.parse();
 PDF pdf = output.getPDF();
 pdf.render(new FileOutputStream("out.pdf"));
 

XML isn't the only way to represent data; the technique of manually adding a processing instruction can also be applied to data stored as JSON, CBOR, or a java.util.Map. For JSON or CBOR it is parsed the same way as XML; any stream, file or URL with a media-type of application/json or application/cbor will be passed through ZTemplate, so long as the ztemplate processing-instruction has been added via the API. So to convert JSON, the code sample directly above would be modified only to change the file to JSON, eg report.load(new File("data.json"));


 Report report = reportFactory.createReport();
 ProcessingInstruction pi = new ProcessingInstruction("ztemplate", "href=\"path/to/template.ztl\"");
 report.getProcessingInstructions().add(pi);
 Map<String,Object> data = loadDataModel();     // Your method
 report.load(data);
 report.parse();
 PDF pdf = output.getPDF();
 pdf.render(new FileOutputStream("out.pdf"));
 

Template format and relative paths

By default the output of any Template is assumed to be HTML (even when the file containing the data is XML, as shown in the first example above). If the template outputs XML instead, set the type attribute on the processing instruction to text/xml. In XML:


 <?ztemplate type="text/html" href="path/to/template.ztl?>
 
or in Java, either of these

 new ProcessingInstruction("ztemplate", "type=\"text/html\" href=\"path/to/template.ztl\"");
 new ProcessingInstruction().setType("ztemplate").put("type", "text/html").put("href", "path/to/template.ztl");
 

Relative paths in the template will be resolved relative to the template file, not relative to the input.

Security

ZTemplate templates are designed not to allow exponential expansion, but for now this API requires they are loaded from a trusted URL - see URLConnectionFactory.isTrusted(org.faceless.publisher.type.URL2). By default this means the resolved Template URL must have a scheme of classpath, file or jar, or if loading from a MemoryURLConnectionFactory the AbstractBlob.isTrusted() method must return true.

Since:
1.3
See Also:
  • Constructor Details

    • ZTemplateExtension

      public ZTemplateExtension()
      Create a new ZTemplateExtension
  • Method Details

    • isThreads

      public boolean isThreads()
      Return the value set by setThreads(boolean)
    • setConfiguration

      public void setConfiguration(Configuration configuration)
      Set the Compiler to use for ZTemplate Templates, to override the default (which is ZTemplate.compiler()). The supplied value will be augmented with Collectors/Formatters for Json and XML. Note calling this method will overwrite anything set by configure(Json)
      Parameters:
      compiler - the compiler
    • configure

      public void configure(Json json)

      Configure the ZTemplate Template compiler. The boolean properties max_iterations, max_output_size, will set the corresponding properties on the Configuration.

      In addition, the boolean parameter threads can be set to call setThreads(boolean)

      Specified by:
      configure in interface ReportFactoryExtension
      Parameters:
      json - the Json configuration
    • unregister

      public void unregister(ReportFactory factory)
      Description copied from interface: ReportFactoryExtension
      Notify this object it has been removed from a ReportFactory. Will be called when this object is removed from the list returned by ReportFactory.getReportFactoryExtensions(). The default implementation is a no-op.
      Specified by:
      unregister in interface ReportFactoryExtension
    • register

      public void register(ReportFactory factory)
      Description copied from interface: ReportFactoryExtension
      Notify this object it has beem added to a ReportFactory. Will be called when this object is added to the list returned by ReportFactory.getReportFactoryExtensions(). The default implementation is a no-op.
      Specified by:
      register in interface ReportFactoryExtension
    • register

      public void register(Report report)
      Description copied from interface: ReportFactoryExtension
      Notify this object it has beem added to a Report. Will be called when this object is added to the list returned by ReportFactory.getReportFactoryExtensions(). The default implementation is a no-op.
      Specified by:
      register in interface ReportFactoryExtension
    • setThreads

      public void setThreads(boolean threads)
      Set whether to use two threads when converting the Template.

      By default only a single thread is used; the output from the template+object is written to a String, and after it completes that String is fed into the XML parser to create the Report.

      Setting threads to true will convert the template+object in a new Thread, with the output from that Thread piped into the main Thread to convert to a Report.

      Depending on the implementation of the template library, using two threads should prevent the entire XML document from being stored in memory, which will be beneficial when small or mid-size templates are combined with large models to create extremely large output.

      Parameters:
      threads - whether to use two Threads when applying the Template
    • load

      public boolean load(Object object, Report report) throws IOException
      Attempt to load the specified object into the specified Report. If a suitable processing-instruction is set and the object can be parsed by the template implementation, the input will be loaded and converted using the template. Otherwise it will return false.
      Specified by:
      load in interface ReportFactoryExtension
      Parameters:
      object - the object to load
      report - the report
      Returns:
      true if this object can be loaded by this extension, false otherwise.
      Throws:
      IOException