1 package de.juplo.thymeleaf;
4 import com.fasterxml.jackson.core.JsonFactory;
5 import com.fasterxml.jackson.core.JsonParser;
6 import com.fasterxml.jackson.core.JsonToken;
7 import com.fasterxml.jackson.databind.JsonNode;
8 import com.fasterxml.jackson.databind.ObjectMapper;
9 import java.io.IOException;
10 import java.io.InputStream;
11 import java.time.format.DateTimeFormatter;
12 import java.util.Locale;
13 import java.util.Map.Entry;
14 import java.util.logging.Level;
15 import org.slf4j.Logger;
16 import org.slf4j.LoggerFactory;
17 import org.springframework.beans.factory.annotation.Autowired;
18 import org.springframework.beans.factory.annotation.Configurable;
19 import org.springframework.context.MessageSource;
20 import org.thymeleaf.Arguments;
21 import org.thymeleaf.Configuration;
22 import org.thymeleaf.TemplateProcessingParameters;
23 import org.thymeleaf.context.IContext;
24 import org.thymeleaf.dom.Element;
25 import org.thymeleaf.processor.ProcessorResult;
26 import org.thymeleaf.processor.attr.AbstractAttrProcessor;
27 import org.thymeleaf.resourceresolver.IResourceResolver;
28 import org.thymeleaf.standard.expression.IStandardExpression;
29 import org.thymeleaf.templateresolver.ITemplateResolver;
30 import org.thymeleaf.templateresolver.TemplateResolution;
31 import org.thymeleaf.util.StringUtils;
40 public class ImportVariablesAttrProcessor extends AbstractAttrProcessor
42 public static final int ATTR_PRECEDENCE = 200;
43 public static final String ATTR_VAR_NAME =
44 JuploDialect.DIALECT_PREFIX + ":var";
45 public static final String ATTR_LOCALE_NAME =
46 JuploDialect.DIALECT_PREFIX + ":locale";
47 public static final String DEFAULT_VAR_NAME = "crumb";
49 private static final Logger LOG =
50 LoggerFactory.getLogger(ImportVariablesAttrProcessor.class);
51 private static final DateTimeFormatter FORMATTER =
52 DateTimeFormatter.ofPattern("dd.MM");
53 private static final ObjectMapper MAPPER = new ObjectMapper();
54 private static final JsonFactory FACTORY = new JsonFactory();
58 MessageSource messageSource;
63 public ImportVariablesAttrProcessor()
70 public final ProcessorResult processAttribute(
71 final Arguments arguments,
72 final Element element,
76 Configuration config = arguments.getConfiguration();
77 String templateName = element.getAttributeValue(name);
79 TemplateProcessingParameters params =
80 new TemplateProcessingParameters(
83 (IContext)null // << We will not execute the template, hence we need no context
86 for (ITemplateResolver t_resolver : config.getTemplateResolvers())
88 TemplateResolution resolution = t_resolver.resolveTemplate(params);
89 if (resolution == null)
91 if (!"JSON".equals(resolution.getTemplateMode()))
93 IResourceResolver r_resolver = resolution.getResourceResolver();
94 InputStream is = r_resolver.getResourceAsStream(params, templateName);
100 /** Read the JSON and create the variables */
101 JsonParser parser = FACTORY.createParser(is);
103 JsonToken root = parser.nextToken();
106 JsonNode root = MAPPER.readTree(is);
110 LOG.warn("found empty content for {}", templateName);
114 if (!root.isObject())
116 LOG.error("{} must contain an object as root-element", templateName);
117 throw new RuntimeException(
118 "The root-element of " +
120 " has to be an object, that contains the variable-definitions!"
124 for (Entry<String, JsonNode> entry : root.fields())
126 Object var = ImportVariablesAttrProcessor.convert(root.get(i));
127 element.setNodeLocalVariable(name, var);
130 catch (IOException e)
132 LOG.error("cannot parse {} as JSON: {}", templateName, e.getMessage());
133 throw new RuntimeException(e);
137 element.removeAttribute(name);
139 return ProcessorResult.OK;
144 public int getPrecedence()
146 return ATTR_PRECEDENCE;
150 public static Object convert(JsonNode node)