Implemented juplo:variables, that imports variables from JSON-data
authorKai Moritz <kai@juplo.de>
Sat, 18 Jun 2016 10:26:02 +0000 (12:26 +0200)
committerKai Moritz <kai@juplo.de>
Mon, 18 Jul 2016 14:54:59 +0000 (16:54 +0200)
The processor interprets its argument as name of a thymeleaf-template and
parses the retrieved template as JSON-data. The root-element of the JSON-
data has to be an object. The variables, that are defined in this object,
are imported as node-local variables.

pom.xml
src/main/java/de/juplo/thymeleaf/ImportVariablesAttrProcessor.java [new file with mode: 0644]
src/main/java/de/juplo/thymeleaf/JuploDialect.java

diff --git a/pom.xml b/pom.xml
index 485b597..6daf99a 100644 (file)
--- a/pom.xml
+++ b/pom.xml
@@ -9,15 +9,26 @@
   <properties>
     <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
     <java.version>1.8</java.version>
+    <simple-mapper.version>1.0.0</simple-mapper.version>
     <thymeleaf.version>2.1.5.RELEASE</thymeleaf.version>
   </properties>
 
+
   <dependencies>
+
     <dependency>
       <groupId>org.thymeleaf</groupId>
       <artifactId>thymeleaf</artifactId>
       <version>${thymeleaf.version}</version>
     </dependency>
+
+    <!-- Needed to parse JSON -->
+    <dependency>
+      <groupId>de.juplo.jackson</groupId>
+      <artifactId>simple-mapper</artifactId>
+      <version>${simple-mapper.version}</version>
+    </dependency>
+
   </dependencies>
 
   <build>
diff --git a/src/main/java/de/juplo/thymeleaf/ImportVariablesAttrProcessor.java b/src/main/java/de/juplo/thymeleaf/ImportVariablesAttrProcessor.java
new file mode 100644 (file)
index 0000000..f679591
--- /dev/null
@@ -0,0 +1,127 @@
+package de.juplo.thymeleaf;
+
+
+import com.fasterxml.jackson.core.JsonFactory;
+import de.juplo.jackson.SimpleMapper;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Iterator;
+import java.util.Locale;
+import java.util.Map.Entry;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.thymeleaf.Arguments;
+import org.thymeleaf.Configuration;
+import org.thymeleaf.TemplateProcessingParameters;
+import org.thymeleaf.context.IContext;
+import org.thymeleaf.context.VariablesMap;
+import org.thymeleaf.dom.Element;
+import org.thymeleaf.processor.ProcessorResult;
+import org.thymeleaf.processor.attr.AbstractAttrProcessor;
+import org.thymeleaf.resourceresolver.IResourceResolver;
+import org.thymeleaf.templateresolver.ITemplateResolver;
+import org.thymeleaf.templateresolver.TemplateResolution;
+
+
+
+/**
+ * Retrievs and parses JSON-data and imports the parsed variables as node-local
+ * variables.
+ * @author Kai Moritz
+ */
+public class ImportVariablesAttrProcessor extends AbstractAttrProcessor
+{
+  public static final int ATTR_PRECEDENCE = 200;
+
+  private static final Logger LOG =
+      LoggerFactory.getLogger(ImportVariablesAttrProcessor.class);
+  private static final JsonFactory FACTORY = new JsonFactory();
+
+
+  public ImportVariablesAttrProcessor()
+  {
+    super("variables");
+  }
+
+
+  @Override
+  public final ProcessorResult processAttribute(
+      final Arguments arguments,
+      final Element element,
+      final String name
+      )
+  {
+    Configuration config = arguments.getConfiguration();
+    String templateName = element.getAttributeValue(name);
+
+    TemplateProcessingParameters params =
+        new TemplateProcessingParameters(
+            config,
+            templateName,
+            new IContext() // << We will not execute the template, hence we need no context
+            {
+              @Override
+              public VariablesMap<String, Object> getVariables()
+              {
+                return new VariablesMap<>();
+              }
+
+              @Override
+              public Locale getLocale()
+              {
+                return Locale.getDefault();
+              }
+
+              @Override
+              public void addContextExecutionInfo(String templateName)
+              {
+              }
+            });
+
+    for (ITemplateResolver t_resolver : config.getTemplateResolvers())
+    {
+      TemplateResolution resolution = t_resolver.resolveTemplate(params);
+      if (resolution == null)
+        continue;
+      if (!"JSON".equals(resolution.getTemplateMode()))
+        continue;
+      IResourceResolver r_resolver = resolution.getResourceResolver();
+      InputStream is =
+          r_resolver.getResourceAsStream(params, resolution.getResourceName());
+      if (is == null)
+        continue;
+
+      try
+      {
+        Iterator<Entry<String, Object>> it =
+            SimpleMapper.getObjectIterator(FACTORY.createParser(is));
+        while(it.hasNext())
+        {
+          Entry<String, Object> entry = it.next();
+          element.setNodeLocalVariable(entry.getKey(), entry.getValue());
+        }
+      }
+      catch (IOException e)
+      {
+        LOG.error("cannot retreive {} as JSON: {}", templateName, e.getMessage());
+        throw new RuntimeException(e);
+      }
+      catch (IllegalArgumentException e)
+      {
+        LOG.error("cannot parse {} as JSON: {}", templateName, e.getMessage());
+        throw new RuntimeException(e);
+      }
+    }
+
+    element.removeAttribute(name);
+
+    return ProcessorResult.OK;
+  }
+
+
+  @Override
+  public int getPrecedence()
+  {
+    return ATTR_PRECEDENCE;
+  }
+}
index 599791b..e4d2d5b 100644 (file)
@@ -13,6 +13,9 @@ import org.thymeleaf.processor.IProcessor;
  */
 public class JuploDialect extends AbstractDialect
 {
+  public static final String DIALECT_PREFIX = "juplo";
+
+
   public JuploDialect()
   {
     super();
@@ -22,7 +25,7 @@ public class JuploDialect extends AbstractDialect
   @Override
   public String getPrefix()
   {
-    return "juplo";
+    return DIALECT_PREFIX;
   }
 
   @Override
@@ -31,6 +34,7 @@ public class JuploDialect extends AbstractDialect
     final Set<IProcessor> processors = new HashSet<>();
     processors.add(new ActiveAttrProcessor());
     processors.add(new InactiveAttrProcessor());
+    processors.add(new ImportVariablesAttrProcessor());
     return processors;
   }
 }