Ported app to Thymeleaf 3.0.x
authorKai Moritz <kai@juplo.de>
Mon, 27 Feb 2017 17:47:26 +0000 (18:47 +0100)
committerKai Moritz <kai@juplo.de>
Tue, 11 Feb 2020 20:50:26 +0000 (21:50 +0100)
 * Proted the dialect to the new Thymeleaf-API
 * Removed modified configuration of the default-template-resolver, because
   it is not needed any more: Thymeleaf 3.0.x resolves its templates via
   Spring's resource-chain by default.

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

diff --git a/pom.xml b/pom.xml
index 896f59a..8a5be94 100644 (file)
--- a/pom.xml
+++ b/pom.xml
@@ -41,6 +41,7 @@
     <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>3.0.3.RELEASE</thymeleaf.version>
   </properties>
 
 
@@ -78,7 +79,7 @@
         <!-- Import dependency management from Spring Boot -->
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-dependencies</artifactId>
-        <version>1.3.6.RELEASE</version>
+        <version>1.5.1.RELEASE</version>
         <type>pom</type>
         <scope>import</scope>
       </dependency>
diff --git a/src/main/java/de/juplo/thymeleaf/ImportVariablesAttrProcessor.java b/src/main/java/de/juplo/thymeleaf/ImportVariablesAttrProcessor.java
deleted file mode 100644 (file)
index aac37a6..0000000
+++ /dev/null
@@ -1,314 +0,0 @@
-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.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Locale;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-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.dom.Node;
-import org.thymeleaf.exceptions.TemplateProcessingException;
-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.standard.expression.IStandardExpressionParser;
-import org.thymeleaf.standard.expression.StandardExpressions;
-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
-{
-  private static final Logger LOG =
-      LoggerFactory.getLogger(ImportVariablesAttrProcessor.class);
-  private static final JsonFactory FACTORY = new JsonFactory();
-  private static final String PROPERTY_NAME =
-      ImportVariablesAttrProcessor.class.getCanonicalName() + "_VARIABLES";
-
-  public static final Pattern PATTERN =
-      Pattern.compile(
-          "^\\s*(?:(?:(merge)|replace):)?\\s*(?:(\\{.*\\})|(.*))\\s*$",
-          Pattern.DOTALL | Pattern.CASE_INSENSITIVE
-          );
-  public static final int ATTR_PRECEDENCE = 200;
-
-
-  public ImportVariablesAttrProcessor()
-  {
-    super("variables");
-  }
-
-
-  @Override
-  public final ProcessorResult processAttribute(
-      final Arguments arguments,
-      final Element element,
-      final String name
-      )
-  {
-    Configuration config = arguments.getConfiguration();
-
-    Configuration configuration = arguments.getConfiguration();
-
-    String parameter = element.getAttributeValue(name);
-    try
-    {
-      IStandardExpressionParser parser =
-          StandardExpressions.getExpressionParser(configuration);
-      IStandardExpression expression =
-          parser.parseExpression(configuration, arguments, parameter);
-      parameter = (String)expression.execute(configuration, arguments);
-    }
-    catch (TemplateProcessingException e) { }
-
-    if (parameter != null && !parameter.trim().isEmpty())
-    {
-      LOG.info("ignoring empty parameter");
-      return ProcessorResult.OK;
-    }
-
-    Iterator<Entry<String, Object>> it = null;
-
-    Matcher matcher = PATTERN.matcher(parameter);
-    boolean merge = false;
-    String json = null;
-    String resource = parameter;
-
-    if (matcher.matches())
-    {
-      merge = matcher.group(1) != null;
-      json = matcher.group(2);
-      resource = matcher.group(3);
-    }
-
-    if (json != null)
-    {
-      LOG.info("parsing parameter as JSON");
-      LOG.debug("parameter: {}", json);
-      try
-      {
-        it = SimpleMapper.getObjectIterator(FACTORY.createParser(json));
-      }
-      catch (IOException e)
-      {
-        LOG.error("cannot parse parameter as JSON: {}", json, e.getMessage());
-        throw new RuntimeException(e);
-      }
-    }
-    else
-    {
-      LOG.info("retriving {} as JSON-template", resource);
-      TemplateProcessingParameters params =
-          new TemplateProcessingParameters(
-              config,
-              resource,
-              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
-        {
-          it = SimpleMapper.getObjectIterator(FACTORY.createParser(is));
-          break;
-        }
-        catch (IOException | IllegalArgumentException e)
-        {
-          LOG.error("cannot retreive {} as JSON: {}", parameter, e.getMessage());
-          throw new RuntimeException(e);
-        }
-      }
-
-      if (it == null)
-      {
-        LOG.error("cannot resolve {} as JSON (not found)!", parameter);
-        throw new RuntimeException("Template not found: " + parameter);
-      }
-    }
-
-    try
-    {
-      Map<String, Object> variables = getVariables(element);
-      if (merge)
-      {
-        while(it.hasNext())
-        {
-          Entry<String, Object> variable = it.next();
-          String key = variable.getKey();
-          Object value = variable.getValue();
-          Object existing = variables.get(key);
-          if (existing != null)
-          {
-            if (value instanceof String)
-            {
-              if (!(existing instanceof String))
-              {
-                LOG.error(
-                    "cannot merge variable {} of type {} with a string",
-                    key,
-                    existing.getClass()
-                    );
-                throw new RuntimeException(
-                    "Type-Missmatch for variable  " + key
-                    );
-              }
-
-              String string = ((String)existing).concat((String) value);
-              LOG.info("appending variable to string {}", key);
-              element.setNodeLocalVariable(key, string);
-            }
-            else if (value instanceof Map)
-            {
-              if (!(existing instanceof Map))
-              {
-                LOG.error(
-                    "cannot merge variable {} of type {} with a map",
-                    key,
-                    existing.getClass()
-                    );
-                throw new RuntimeException(
-                    "Type-Missmatch for variable  " + key
-                    );
-              }
-
-              Map map = ((Map)existing);
-              map.putAll((Map) value);
-              LOG.info("merging variable with map {}", key);
-              element.setNodeLocalVariable(key, map);
-            }
-            else if (value instanceof List)
-            {
-              if (!(existing instanceof List))
-              {
-                LOG.error(
-                    "cannot merge variable {} of type {} with a list",
-                    key,
-                    existing.getClass()
-                    );
-                throw new RuntimeException(
-                    "Type-Missmatch for variable  " + key
-                    );
-              }
-
-              List list = ((List)existing);
-              list.addAll((List) value);
-              LOG.info("appending contents of variable to list {}", key);
-              element.setNodeLocalVariable(key, list);
-            }
-            else
-            {
-              LOG.error(
-                  "variable {} is of unexpected type {}", key, value.getClass()
-                  );
-              throw new RuntimeException(
-                  "Found variable of unexpected type: " + key
-                  );
-            }
-          }
-          else
-          {
-            LOG.info("adding new variable {}", key);
-            element.setNodeLocalVariable(key, value);
-          }
-        }
-      }
-      else
-        while(it.hasNext())
-        {
-          Entry<String, Object> variable = it.next();
-          String key = variable.getKey();
-          Object value = variable.getValue();
-          LOG.info("adding variable {}", key);
-          variables.put(key, value);
-          element.setNodeLocalVariable(key, value);
-        }
-    }
-    catch (IllegalArgumentException e)
-    {
-      LOG.error("cannot parse {} as JSON: {}", parameter, e.getMessage());
-      throw new RuntimeException(e);
-    }
-
-    element.removeAttribute(name);
-
-    return ProcessorResult.OK;
-  }
-
-
-  Map<String, Object> getVariables(Node node)
-  {
-    Node parent = node;
-    do
-    {
-      Map<String, Object> variables =
-          (Map<String, Object>)parent.getNodeProperty(PROPERTY_NAME);
-
-      if (variables != null)
-        return variables;
-
-      parent = parent.getParent();
-    }
-    while (parent != null);
-
-    Map<String, Object> variables = new HashMap<>();
-    node.setNodeProperty(PROPERTY_NAME, variables);
-    return variables;
-  }
-
-
-  @Override
-  public int getPrecedence()
-  {
-    return ATTR_PRECEDENCE;
-  }
-}
diff --git a/src/main/java/de/juplo/thymeleaf/ImportVariablesAttributeProcessor.java b/src/main/java/de/juplo/thymeleaf/ImportVariablesAttributeProcessor.java
new file mode 100644 (file)
index 0000000..4190767
--- /dev/null
@@ -0,0 +1,382 @@
+package de.juplo.thymeleaf;
+
+
+import com.fasterxml.jackson.core.JsonFactory;
+import de.juplo.jackson.SimpleMapper;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+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.dom.Node;
+import org.thymeleaf.IEngineConfiguration;
+import org.thymeleaf.context.ITemplateContext;
+import org.thymeleaf.engine.AttributeName;
+import org.thymeleaf.engine.EngineEventUtils;
+import org.thymeleaf.exceptions.TemplateProcessingException;
+import org.thymeleaf.model.IProcessableElementTag;
+import org.thymeleaf.processor.element.AbstractAttributeTagProcessor;
+import org.thymeleaf.processor.element.IElementTagStructureHandler;
+import org.thymeleaf.standard.expression.FragmentExpression;
+import org.thymeleaf.standard.expression.FragmentExpression.ExecutedFragmentExpression;
+import org.thymeleaf.standard.expression.IStandardExpression;
+import org.thymeleaf.standard.expression.NoOpToken;
+import org.thymeleaf.standard.expression.StandardExpressionExecutionContext;
+import org.thymeleaf.templatemode.TemplateMode;
+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 ImportVariablesAttributeProcessor extends AbstractAttributeTagProcessor
+{
+  private static final Logger LOG =
+      LoggerFactory.getLogger(ImportVariablesAttributeProcessor.class);
+  private static final JsonFactory FACTORY = new JsonFactory();
+  private static final String PROPERTY_NAME =
+      ImportVariablesAttributeProcessor.class.getCanonicalName() + "_VARIABLES";
+
+  public static final Pattern PATTERN =
+      Pattern.compile(
+          "^\\s*(?:(?:(merge)|replace):)?\\s*(?:(\\{.*\\})|(.*))\\s*$",
+          Pattern.DOTALL | Pattern.CASE_INSENSITIVE
+          );
+
+  public static final String ATTR_NAME = "variables";
+  public static final int ATTR_PRECEDENCE = 200;
+
+
+  public ImportVariablesAttributeProcessor(String prefix)
+  {
+    super(TemplateMode.HTML, prefix, null, false, ATTR_NAME, true, ATTR_PRECEDENCE, true);
+  }
+
+
+  @Override
+  protected void doProcess(
+      final ITemplateContext context,
+      final IProcessableElementTag element,
+      final AttributeName name,
+      final String attribute,
+      final IElementTagStructureHandler handler
+      )
+  {
+    if (attribute == null)
+      return;
+
+    String location;
+    try
+    {
+      final Object result;
+      final IStandardExpression expression =
+         EngineEventUtils.computeAttributeExpression(
+             context,
+             element,
+             name,
+             attribute
+             );
+
+      if (expression != null && expression instanceof FragmentExpression)
+      {
+        final ExecutedFragmentExpression executedFragmentExpression =
+            FragmentExpression.createExecutedFragmentExpression(
+                context,
+                (FragmentExpression) expression,
+                StandardExpressionExecutionContext.NORMAL
+                );
+        result =
+            FragmentExpression.resolveExecutedFragmentExpression(
+                context,
+                executedFragmentExpression,
+                true
+                );
+      }
+      else
+      {
+        result = expression.execute(context);
+      }
+
+      // If the result of this expression is NO-OP, there is nothing to execute
+      if (result == NoOpToken.VALUE)
+      {
+        handler.removeAttribute(name);
+        return;
+      }
+
+      location = result.toString();
+    }
+    catch (final TemplateProcessingException e)
+    {
+      location = attribute;
+    }
+
+
+    Iterator<Entry<String, Object>> it = null;
+
+    Matcher matcher = PATTERN.matcher(location);
+    boolean merge = false;
+    String json = null;
+
+    if (matcher.matches())
+    {
+      merge = matcher.group(1) != null;
+      json = matcher.group(2);
+      location = matcher.group(3);
+    }
+
+    if (json != null)
+    {
+      LOG.info("parsing parameter as JSON");
+      LOG.debug("parameter: {}", json);
+      try
+      {
+        it = SimpleMapper.getObjectIterator(FACTORY.createParser(json));
+      }
+      catch (IOException e)
+      {
+        LOG.error("cannot parse parameter as JSON: {}", json, e.getMessage());
+        return;
+      }
+    }
+    else
+    {
+      LOG.info("retriving {} as Spring-resource", location);
+      IEngineConfiguration config = context.getConfiguration();
+      for (ITemplateResolver resolver : config.getTemplateResolvers())
+      {
+        TemplateResolution resolution =
+            resolver.resolveTemplate(
+                config,
+                context.getTemplateData().getTemplate(),
+                location,
+                null
+                );
+        if (resolution != null)
+        {
+          try
+          {
+            it = SimpleMapper.getObjectIterator(FACTORY.createParser(resolution.getTemplateResource().reader()));
+            break;
+          }
+          catch (IOException e) {}
+        }
+      }
+
+      if (it == null)
+      {
+        LOG.error("cannot resolve {} as JSON (not found)!", location);
+        return;
+      }
+    }
+
+    try
+    {
+      Map<String, Object> variables = getVariables(context);
+      if (merge)
+      {
+        while(it.hasNext())
+        {
+          Entry<String, Object> variable = it.next();
+          String key = variable.getKey();
+          Object value = variable.getValue();
+          Object existing = context.getVariable(key);
+          if (existing != null)
+          {
+            if (value instanceof String)
+            {
+              if (!(existing instanceof String))
+              {
+                LOG.error(
+                    "cannot merge variable {} of type {} with a string",
+                    key,
+                    existing.getClass()
+                    );
+                throw new RuntimeException(
+                    "Type-Missmatch for variable  " + key
+                    );
+              }
+
+              String string = ((String)existing).concat((String) value);
+              LOG.info("appending variable to string {}", key);
+              handler.setLocalVariable(key, string);
+            }
+            else if (value instanceof Map)
+            {
+              if (!(existing instanceof Map))
+              {
+                LOG.error(
+                    "cannot merge variable {} of type {} with a map",
+                    key,
+                    existing.getClass()
+                    );
+                throw new RuntimeException(
+                    "Type-Missmatch for variable  " + key
+                    );
+              }
+
+              Map map = ((Map)existing);
+              map.putAll((Map) value);
+              LOG.info("merging variable with map {}", key);
+              handler.setLocalVariable(key, map);
+            }
+            else if (value instanceof List)
+            {
+              if (!(existing instanceof List))
+              {
+                LOG.error(
+                    "cannot merge variable {} of type {} with a list",
+                    key,
+                    existing.getClass()
+                    );
+                throw new RuntimeException(
+                    "Type-Missmatch for variable  " + key
+                    );
+              }
+
+              List list = ((List)existing);
+              list.addAll((List) value);
+              LOG.info("appending contents of variable to list {}", key);
+              handler.setLocalVariable(key, list);
+            }
+            else
+            {
+              LOG.error(
+                  "variable {} is of unexpected type {}", key, value.getClass()
+                  );
+              throw new RuntimeException(
+                  "Found variable of unexpected type: " + key
+                  );
+            }
+          }
+          else
+          {
+            LOG.info("adding new variable {}", key);
+            handler.setLocalVariable(key, value);
+          }
+        }
+      }
+      else
+        while(it.hasNext())
+        {
+          Entry<String, Object> variable = it.next();
+          String key = variable.getKey();
+          Object value = variable.getValue();
+          LOG.info("adding variable {}", key);
+          variables.put(key, value);
+          handler.setLocalVariable(key, value);
+        }
+    }
+    catch (IllegalArgumentException e)
+    {
+      LOG.error("cannot parse {} as JSON: {}", location, e.getMessage());
+      throw new RuntimeException(e);
+    }
+
+    handler.removeAttribute(name);
+  }
+
+
+  Map<String, Object> getVariables(ITemplateContext context)
+  {
+    Map<String, Object> variables = new HashMap<>();
+    return variables;
+  }
+
+
+  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
+  }
+
+  static Map<String, Object> convertObject(JsonParser parser) throws IOException
+  {
+    JsonToken token = parser.nextToken();
+    if (token == null)
+      fail(parser, "unexpected EOF");
+
+    Map<String, Object> 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<Object> convertArray(JsonParser parser) throws IOException
+  {
+    JsonToken token = parser.nextToken();
+    if (token == null)
+      fail(parser, "unexpected EOF");
+
+    List<Object> 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;
+  }
+
+  static void fail(JsonParser parser, String message)
+  {
+    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);
+  }
+}
index e4d2d5b..f6e2e96 100644 (file)
@@ -3,7 +3,7 @@ package de.juplo.thymeleaf;
 
 import java.util.HashSet;
 import java.util.Set;
-import org.thymeleaf.dialect.AbstractDialect;
+import org.thymeleaf.dialect.IProcessorDialect;
 import org.thymeleaf.processor.IProcessor;
 
 
@@ -11,17 +11,18 @@ import org.thymeleaf.processor.IProcessor;
  * A collection of usefull tools.
  * @author Kai Moritz
  */
-public class JuploDialect extends AbstractDialect
+public class JuploDialect implements IProcessorDialect
 {
   public static final String DIALECT_PREFIX = "juplo";
+  public static final int DIALEXT_PRECEDENCE = 200;
 
 
-  public JuploDialect()
+  @Override
+  public String getName()
   {
-    super();
+    return DIALECT_PREFIX;
   }
 
-
   @Override
   public String getPrefix()
   {
@@ -29,12 +30,18 @@ public class JuploDialect extends AbstractDialect
   }
 
   @Override
-  public Set<IProcessor> getProcessors()
+  public int getDialectProcessorPrecedence()
+  {
+    return DIALEXT_PRECEDENCE;
+  }
+
+  @Override
+  public Set<IProcessor> getProcessors(final String prefix)
   {
     final Set<IProcessor> processors = new HashSet<>();
     processors.add(new ActiveAttrProcessor());
     processors.add(new InactiveAttrProcessor());
-    processors.add(new ImportVariablesAttrProcessor());
+    processors.add(new ImportVariablesAttributeProcessor(prefix));
     return processors;
   }
 }
index e8e188e..d36c26d 100644 (file)
@@ -23,51 +23,51 @@ public class ImportVariablesAttrProcessorTest
   {
     Matcher matcher;
 
-    matcher = ImportVariablesAttrProcessor.PATTERN.matcher("{}");
+    matcher = ImportVariablesAttributeProcessor.PATTERN.matcher("{}");
     assertTrue(matcher.matches());
-    matcher = ImportVariablesAttrProcessor.PATTERN.matcher(" { } ");
+    matcher = ImportVariablesAttributeProcessor.PATTERN.matcher(" { } ");
     assertTrue(matcher.matches());
-    matcher = ImportVariablesAttrProcessor.PATTERN.matcher("\t{\t}\t");
+    matcher = ImportVariablesAttributeProcessor.PATTERN.matcher("\t{\t}\t");
     assertTrue(matcher.matches());
-    matcher = ImportVariablesAttrProcessor.PATTERN.matcher("\n{\n}\n");
+    matcher = ImportVariablesAttributeProcessor.PATTERN.matcher("\n{\n}\n");
     assertTrue(matcher.matches());
-    matcher = ImportVariablesAttrProcessor.PATTERN.matcher(" \t\n{ \t\n} \t\n");
+    matcher = ImportVariablesAttributeProcessor.PATTERN.matcher(" \t\n{ \t\n} \t\n");
     assertTrue(matcher.matches());
 
-    matcher = ImportVariablesAttrProcessor.PATTERN.matcher("{\"foo\":\"bar\",\"foobar\":{\"foo\":\"bar\"}");
+    matcher = ImportVariablesAttributeProcessor.PATTERN.matcher("{\"foo\":\"bar\",\"foobar\":{\"foo\":\"bar\"}");
     assertTrue(matcher.matches());
-    matcher = ImportVariablesAttrProcessor.PATTERN.matcher(" { \"foo\":\"bar\", \"foobar\": { \"foo\": \"bar\" } ");
+    matcher = ImportVariablesAttributeProcessor.PATTERN.matcher(" { \"foo\":\"bar\", \"foobar\": { \"foo\": \"bar\" } ");
     assertTrue(matcher.matches());
-    matcher = ImportVariablesAttrProcessor.PATTERN.matcher("\t{\t\"foo\":\t\"bar\"\t,\t\"foobar\":\t{\t\"foo\":\"bar\"\t}");
+    matcher = ImportVariablesAttributeProcessor.PATTERN.matcher("\t{\t\"foo\":\t\"bar\"\t,\t\"foobar\":\t{\t\"foo\":\"bar\"\t}");
     assertTrue(matcher.matches());
-    matcher = ImportVariablesAttrProcessor.PATTERN.matcher("\n{\n\"foo\":\n\"bar\"\n,\n\"foobar\":\n{\n\"foo\":\"bar\"\n}");
+    matcher = ImportVariablesAttributeProcessor.PATTERN.matcher("\n{\n\"foo\":\n\"bar\"\n,\n\"foobar\":\n{\n\"foo\":\"bar\"\n}");
     assertTrue(matcher.matches());
-    matcher = ImportVariablesAttrProcessor.PATTERN.matcher("\n\t {\n\t \"foo\":\n\t \"bar\"\n\t ,\n\t \"foobar\":\n\t {\n\t \"foo\":\"bar\"\n\t }");
+    matcher = ImportVariablesAttributeProcessor.PATTERN.matcher("\n\t {\n\t \"foo\":\n\t \"bar\"\n\t ,\n\t \"foobar\":\n\t {\n\t \"foo\":\"bar\"\n\t }");
     assertTrue(matcher.matches());
 
     String json;
 
     json = read("/json/1.json");
-    matcher = ImportVariablesAttrProcessor.PATTERN.matcher(json);
+    matcher = ImportVariablesAttributeProcessor.PATTERN.matcher(json);
     assertTrue(matcher.matches());
     json = read("/json/2.json");
-    matcher = ImportVariablesAttrProcessor.PATTERN.matcher(json);
+    matcher = ImportVariablesAttributeProcessor.PATTERN.matcher(json);
     assertTrue(matcher.matches());
     json = read("/json/3.json");
-    matcher = ImportVariablesAttrProcessor.PATTERN.matcher(json);
+    matcher = ImportVariablesAttributeProcessor.PATTERN.matcher(json);
     assertTrue(matcher.matches());
 
-    matcher = ImportVariablesAttrProcessor.PATTERN.matcher("foo:bar");
+    matcher = ImportVariablesAttributeProcessor.PATTERN.matcher("foo:bar");
     assertTrue(matcher.matches());
     assertNull(matcher.group(1));
     assertNull(matcher.group(2));
     assertEquals("foo:bar", matcher.group(3));
-    matcher = ImportVariablesAttrProcessor.PATTERN.matcher("replace:foo");
+    matcher = ImportVariablesAttributeProcessor.PATTERN.matcher("replace:foo");
     assertTrue(matcher.matches());
     assertNull(matcher.group(1));
     assertNull(matcher.group(2));
     assertEquals("foo", matcher.group(3));
-    matcher = ImportVariablesAttrProcessor.PATTERN.matcher("merge:foo");
+    matcher = ImportVariablesAttributeProcessor.PATTERN.matcher("merge:foo");
     assertTrue(matcher.matches());
     assertEquals("merge", matcher.group(1));
     assertNull(matcher.group(2));