X-Git-Url: https://juplo.de/gitweb/?a=blobdiff_plain;f=src%2Fmain%2Fjava%2Fde%2Fjuplo%2Fthymeleaf%2FImportVariablesAttrProcessor.java;h=fe2725ecf35a7614813386666764c9f76cbdec78;hb=3502d6bbe03436d377ed095a7251c1f14a5fba83;hp=bc3f3dae3f6658937b691e175645eb5308af83da;hpb=8b776e8369adb62272bafca7185f90cd0e27b9f0;p=maven-thymeleaf-skin diff --git a/src/main/java/de/juplo/thymeleaf/ImportVariablesAttrProcessor.java b/src/main/java/de/juplo/thymeleaf/ImportVariablesAttrProcessor.java index bc3f3da..fe2725e 100644 --- a/src/main/java/de/juplo/thymeleaf/ImportVariablesAttrProcessor.java +++ b/src/main/java/de/juplo/thymeleaf/ImportVariablesAttrProcessor.java @@ -2,33 +2,19 @@ package de.juplo.thymeleaf; import com.fasterxml.jackson.core.JsonFactory; +import com.fasterxml.jackson.core.JsonLocation; 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 java.util.LinkedHashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; 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; @@ -36,16 +22,8 @@ import org.thymeleaf.util.StringUtils; * * @author kai */ -@Configurable -public class ImportVariablesAttrProcessor extends AbstractAttrProcessor +public class ImportVariablesAttrProcessor { - 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 = @@ -54,101 +32,114 @@ public class ImportVariablesAttrProcessor extends AbstractAttrProcessor private static final JsonFactory FACTORY = new JsonFactory(); - @Autowired - MessageSource messageSource; - @Autowired - Locale defaultLocale; - - - public ImportVariablesAttrProcessor() + public Object processAttribute(InputStream is) { - 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(); + JsonToken token = parser.nextToken(); - - JsonNode root = MAPPER.readTree(is); - - if (root == null) + if (token == null) { - LOG.warn("found empty content for {}", templateName); - break; + LOG.warn("empty input-stream"); + return null; } - 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 entry : root.fields()) - { - Object var = ImportVariablesAttrProcessor.convert(root.get(i)); - element.setNodeLocalVariable(name, var); - } + Object result = convert(parser); + + if (parser.nextToken() != null) + fail(parser, "unexpected data after parsed variables"); + + return result; } catch (IOException e) { - LOG.error("cannot parse {} as JSON: {}", templateName, e.getMessage()); + LOG.error("cannot parse input-stream as JSON: {}", e.getMessage()); throw new RuntimeException(e); } - } + } - element.removeAttribute(name); - return ProcessorResult.OK; - } + static Object convert(JsonParser parser) throws IOException + { + JsonToken token = parser.getCurrentToken(); + if (token == null) + fail(parser, "unexpected EOF"); + + switch (token) + { + case VALUE_STRING: return parser.getText(); + case VALUE_NUMBER_INT: return parser.getIntValue(); + case VALUE_NUMBER_FLOAT: return parser.getDoubleValue(); + case START_OBJECT: return convertObject(parser); + case START_ARRAY: return convertArray(parser); + case VALUE_TRUE: return Boolean.TRUE; + case VALUE_FALSE: return Boolean.FALSE; + case VALUE_NULL: return null; + } + fail(parser, "unexpected token " + token.toString()); + return null; // << Will never be reached, because fail always throws an exception + } - @Override - public int getPrecedence() + static Map convertObject(JsonParser parser) throws IOException { - return ATTR_PRECEDENCE; + JsonToken token = parser.nextToken(); + if (token == null) + fail(parser, "unexpected EOF"); + + Map map = new LinkedHashMap<>(); + + while (!JsonToken.END_OBJECT.equals(token)) + { + if (!JsonToken.FIELD_NAME.equals(token)) + fail(parser, "expected a field-name"); + + String name = parser.getText(); + parser.nextToken(); + Object value = convert(parser); + map.put(name, value); + + token = parser.nextToken(); + if (token == null) + fail(parser, "unexpected EOF"); + } + + return map; } + static List convertArray(JsonParser parser) throws IOException + { + JsonToken token = parser.nextToken(); + if (token == null) + fail(parser, "unexpected EOF"); + + List list = new LinkedList<>(); + + while (!JsonToken.END_ARRAY.equals(token)) + { + list.add(convert(parser)); + + token = parser.nextToken(); + if (token == null) + fail(parser, "unexpected EOF"); + } + + return list; + } - public static Object convert(JsonNode node) + static void fail(JsonParser parser, String message) { - return null; + JsonLocation location = parser.getCurrentLocation(); + LOG.error( + "{} at char-offset {} (line {}, column {})", + message, + location.getCharOffset(), + location.getLineNr(), + location.getColumnNr() + ); + throw new RuntimeException("Cannot parse JSON: " + message); } }