--- /dev/null
+package org.argeo.cms.script;
+
+import javax.jcr.Node;
+import javax.jcr.RepositoryException;
+
+import org.argeo.cms.ui.fm.FmUiProvider;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+
+public class Html {
+ private String template;
+ private Node context;
+
+ private Control control;
+
+ public Html(Composite parent, String template, Node context) throws RepositoryException {
+ this.template = template;
+ this.context = context;
+ this.control = new FmUiProvider(this.template).createUi(parent, context);
+ }
+
+ public Html(Composite parent, String template) throws RepositoryException {
+ this(parent, template, null);
+ }
+
+ public String getTemplate() {
+ return template;
+ }
+
+ public Node getContext() {
+ return context;
+ }
+
+ public Control getControl() {
+ return control;
+ }
+
+}
--- /dev/null
+package org.argeo.cms.ui.fm;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.StringWriter;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.jcr.Node;
+import javax.jcr.RepositoryException;
+
+import org.argeo.cms.ui.CmsUiProvider;
+import org.argeo.fm.jcr.JcrModel;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.browser.Browser;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+
+import freemarker.template.Configuration;
+import freemarker.template.Template;
+import freemarker.template.TemplateExceptionHandler;
+
+public class FmUiProvider implements CmsUiProvider {
+ static Configuration cfg;
+ static {
+ try {
+ cfg = new Configuration(Configuration.VERSION_2_3_28);
+ cfg.setDirectoryForTemplateLoading(new File(System.getProperty("user.home") + File.separator + "dev"
+ + File.separator + "work" + File.separator + "ftl"));
+ cfg.setDefaultEncoding("UTF-8");
+ cfg.setTemplateExceptionHandler(TemplateExceptionHandler.HTML_DEBUG_HANDLER);
+ cfg.setLogTemplateExceptions(false);
+ cfg.setWrapUncheckedExceptions(true);
+ } catch (IOException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
+
+ private String template;
+
+ public FmUiProvider(String template) {
+ this.template = template;
+ }
+
+ @Override
+ public Control createUi(Composite parent, Node context) throws RepositoryException {
+ Browser browser = new Browser(parent, SWT.NONE);
+ try {
+ Map<String, Object> root = new HashMap<>();
+ if (context != null)
+ root.put("node", new JcrModel(context));
+
+ Template temp = cfg.getTemplate(template);
+ StringWriter out = new StringWriter();
+ temp.process(root, out);
+ browser.setText(out.toString());
+ } catch (Exception e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+
+ return browser;
+ }
+
+}
#Main-Class: org.argeo.sync.cli.Sync
+
+Import-Package: *;resolution:=optional
\ No newline at end of file
--- /dev/null
+package org.argeo.fm;
+
+/**
+ * Product bean; note that it must be a public class!
+ */
+public class Product {
+
+ private String url;
+ private String name;
+
+ // As per the JavaBeans spec., this defines the "url" bean property
+ // It must be public!
+ public String getUrl() {
+ return url;
+ }
+
+ public void setUrl(String url) {
+ this.url = url;
+ }
+
+ // As per the JavaBean spec., this defines the "name" bean property
+ // It must be public!
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+}
\ No newline at end of file
--- /dev/null
+package org.argeo.fm;
+
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.Writer;
+import java.util.HashMap;
+import java.util.Map;
+
+import freemarker.template.Configuration;
+import freemarker.template.Template;
+import freemarker.template.TemplateExceptionHandler;
+
+public class TestFreeMarker {
+ static String base = System.getProperty("user.home") + File.separator + "dev" + File.separator + "work"
+ + File.separator + "ftl";
+ static Configuration cfg;
+ static {
+ try {
+ cfg = new Configuration(Configuration.VERSION_2_3_28);
+ cfg.setDirectoryForTemplateLoading(new File(base));
+ cfg.setDefaultEncoding("UTF-8");
+ cfg.setTemplateExceptionHandler(TemplateExceptionHandler.HTML_DEBUG_HANDLER);
+ cfg.setLogTemplateExceptions(false);
+ cfg.setWrapUncheckedExceptions(true);
+ } catch (IOException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
+
+ public static void main(String[] args) {
+ if (args.length == 0) {
+ System.err.println("Usage: <template name> (in " + base + ")");
+ }
+ String template = args[0];
+ try {
+ /* Create a data-model */
+ Map<String, Object> root = new HashMap<>();
+ root.put("user", "Big Joe");
+ Product latest = new Product();
+ latest.setUrl("products/greenmouse.html");
+ latest.setName("green mouse");
+ root.put("latestProduct", latest);
+
+ /* Get the template (uses cache internally) */
+ Template temp = cfg.getTemplate(template);
+
+ /* Merge data-model with template */
+ String target = base + File.separator + template + ".html";
+ Writer out = new FileWriter(target);
+ temp.process(root, out);
+ out.flush();
+ System.out.println("Wrote " + target);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+}
--- /dev/null
+package org.argeo.fm.jcr;
+
+import javax.jcr.Node;
+import javax.jcr.Property;
+import javax.jcr.RepositoryException;
+
+import freemarker.template.SimpleScalar;
+import freemarker.template.TemplateHashModel;
+import freemarker.template.TemplateModel;
+import freemarker.template.TemplateModelException;
+import freemarker.template.TemplateNodeModel;
+import freemarker.template.TemplateSequenceModel;
+
+public class JcrModel implements TemplateNodeModel, TemplateHashModel {
+ private final Node node;
+
+ public JcrModel(Node node) {
+ this.node = node;
+ }
+
+ @Override
+ public TemplateSequenceModel getChildNodes() throws TemplateModelException {
+ try {
+ return new NodeIteratorModel(node.getNodes());
+ } catch (RepositoryException e) {
+ throw new TemplateModelException("Cannot list children of " + node, e);
+ }
+ }
+
+ @Override
+ public String getNodeName() throws TemplateModelException {
+ try {
+ return node.getName();
+ } catch (RepositoryException e) {
+ throw new TemplateModelException("Cannot get name of " + node, e);
+ }
+ }
+
+ @Override
+ public String getNodeNamespace() throws TemplateModelException {
+ // TODO find out namespace
+ return null;
+ }
+
+ @Override
+ public String getNodeType() throws TemplateModelException {
+ try {
+ return node.getPrimaryNodeType().getName();
+ } catch (RepositoryException e) {
+ throw new TemplateModelException("Cannot get node type of " + node, e);
+ }
+ }
+
+ @Override
+ public TemplateNodeModel getParentNode() throws TemplateModelException {
+ try {
+ Node parent = node.getParent();
+ if (parent == null)
+ return null;
+ return new JcrModel(parent);
+ } catch (RepositoryException e) {
+ throw new TemplateModelException("Cannot get parent of " + node, e);
+ }
+ }
+
+ @Override
+ public TemplateModel get(String key) throws TemplateModelException {
+ try {
+ Property property = node.getProperty(key);
+ if (property == null)
+ return null;
+ return new SimpleScalar(property.getString());
+ } catch (RepositoryException e) {
+ throw new TemplateModelException("Cannot get property " + key + " of " + node, e);
+ }
+ }
+
+ @Override
+ public boolean isEmpty() throws TemplateModelException {
+ // JCR default properties always accessible
+ return false;
+ }
+
+ // HASH
+
+}
--- /dev/null
+package org.argeo.fm.jcr;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.jcr.Node;
+import javax.jcr.NodeIterator;
+
+import freemarker.template.TemplateModel;
+import freemarker.template.TemplateModelException;
+import freemarker.template.TemplateSequenceModel;
+
+public class NodeIteratorModel implements TemplateSequenceModel {
+ private final NodeIterator nodeIterator;
+
+ private final List<Node> nodes;
+ private int size;
+
+ public NodeIteratorModel(NodeIterator nodeIterator) {
+ super();
+ this.nodeIterator = nodeIterator;
+ this.size = (int) nodeIterator.getSize();
+ this.nodes = new ArrayList<>(this.size);
+ // TODO optimize with lazy loading
+ while (this.nodeIterator.hasNext()) {
+ Node node = this.nodeIterator.nextNode();
+ nodes.add(node);
+ }
+ this.size = nodes.size();
+ }
+
+ @Override
+ public TemplateModel get(int index) throws TemplateModelException {
+ return new JcrModel(nodes.get(index));
+ }
+
+ @Override
+ public int size() throws TemplateModelException {
+ return size;
+ }
+
+}