WIP: variables-dialect
authorKai Moritz <kai@juplo.de>
Sat, 18 Jun 2016 10:26:02 +0000 (12:26 +0200)
committerKai Moritz <kai@juplo.de>
Sat, 18 Jun 2016 10:26:02 +0000 (12:26 +0200)
pom.xml
src/main/java/de/juplo/thymeleaf/ImportVariablesAttrProcessor.java [new file with mode: 0644]
src/main/java/de/juplo/thymeleaf/JuploDialect.java [new file with mode: 0644]

diff --git a/pom.xml b/pom.xml
index b635b71..7529bde 100644 (file)
--- a/pom.xml
+++ b/pom.xml
       <version>${nekohtml.version}</version>
     </dependency>
 
+    <!-- Needed to parse JSON -->
+    <dependency>
+      <groupId>com.fasterxml.jackson.core</groupId>
+      <artifactId>jackson-annotations</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>com.fasterxml.jackson.core</groupId>
+      <artifactId>jackson-core</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>com.fasterxml.jackson.core</groupId>
+      <artifactId>jackson-databind</artifactId>
+    </dependency>
+
     <dependency>
       <groupId>ch.qos.logback</groupId>
       <artifactId>logback-classic</artifactId>
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..bc3f3da
--- /dev/null
@@ -0,0 +1,154 @@
+package de.juplo.thymeleaf;
+
+
+import com.fasterxml.jackson.core.JsonFactory;
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.core.JsonToken;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import java.io.IOException;
+import java.io.InputStream;
+import java.time.format.DateTimeFormatter;
+import java.util.Locale;
+import java.util.Map.Entry;
+import java.util.logging.Level;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Configurable;
+import org.springframework.context.MessageSource;
+import org.thymeleaf.Arguments;
+import org.thymeleaf.Configuration;
+import org.thymeleaf.TemplateProcessingParameters;
+import org.thymeleaf.context.IContext;
+import org.thymeleaf.dom.Element;
+import org.thymeleaf.processor.ProcessorResult;
+import org.thymeleaf.processor.attr.AbstractAttrProcessor;
+import org.thymeleaf.resourceresolver.IResourceResolver;
+import org.thymeleaf.standard.expression.IStandardExpression;
+import org.thymeleaf.templateresolver.ITemplateResolver;
+import org.thymeleaf.templateresolver.TemplateResolution;
+import org.thymeleaf.util.StringUtils;
+
+
+
+/**
+ *
+ * @author kai
+ */
+@Configurable
+public class ImportVariablesAttrProcessor extends AbstractAttrProcessor
+{
+  public static final int ATTR_PRECEDENCE = 200;
+  public static final String ATTR_VAR_NAME =
+      JuploDialect.DIALECT_PREFIX + ":var";
+  public static final String ATTR_LOCALE_NAME =
+      JuploDialect.DIALECT_PREFIX + ":locale";
+  public static final String DEFAULT_VAR_NAME = "crumb";
+
+  private static final Logger LOG =
+      LoggerFactory.getLogger(ImportVariablesAttrProcessor.class);
+  private static final DateTimeFormatter FORMATTER =
+      DateTimeFormatter.ofPattern("dd.MM");
+  private static final ObjectMapper MAPPER = new ObjectMapper();
+  private static final JsonFactory FACTORY = new JsonFactory();
+
+
+  @Autowired
+  MessageSource messageSource;
+  @Autowired
+  Locale defaultLocale;
+
+
+  public ImportVariablesAttrProcessor()
+  {
+    super("crumb");
+  }
+
+
+  @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,
+            (IContext)null // << We will not execute the template, hence we need no context
+            );
+
+    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, templateName);
+      if (is == null)
+        continue;
+
+      try
+      {
+        /** Read the JSON and create the variables */
+        JsonParser parser = FACTORY.createParser(is);
+
+        JsonToken root = parser.nextToken();
+
+
+        JsonNode root = MAPPER.readTree(is);
+
+        if (root == null)
+        {
+          LOG.warn("found empty content for {}", templateName);
+          break;
+        }
+
+        if (!root.isObject())
+        {
+          LOG.error("{} must contain an object as root-element", templateName);
+          throw new RuntimeException(
+              "The root-element of " +
+              templateName +
+              " has to be an object, that contains the variable-definitions!"
+              );
+        }
+root.
+        for (Entry<String, JsonNode> entry : root.fields())
+        {
+          Object var = ImportVariablesAttrProcessor.convert(root.get(i));
+          element.setNodeLocalVariable(name, var);
+        }
+      }
+      catch (IOException 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;
+  }
+
+
+  public static Object convert(JsonNode node)
+  {
+    return null;
+  }
+}
diff --git a/src/main/java/de/juplo/thymeleaf/JuploDialect.java b/src/main/java/de/juplo/thymeleaf/JuploDialect.java
new file mode 100644 (file)
index 0000000..6b127f0
--- /dev/null
@@ -0,0 +1,38 @@
+package de.juplo.thymeleaf;
+
+
+import java.util.HashSet;
+import java.util.Set;
+import org.thymeleaf.dialect.AbstractDialect;
+import org.thymeleaf.processor.IProcessor;
+
+
+/**
+ *
+ * @author kai
+ */
+public class JuploDialect extends AbstractDialect
+{
+  public static final String DIALECT_PREFIX = "juplo";
+
+
+  public JuploDialect()
+  {
+    super();
+  }
+
+
+  @Override
+  public String getPrefix()
+  {
+    return DIALECT_PREFIX;
+  }
+
+  @Override
+  public Set<IProcessor> getProcessors()
+  {
+    final Set<IProcessor> processors = new HashSet<>();
+    processors.add(new ImportVariablesAttrProcessor());
+    return processors;
+  }
+}