TMP
[juplo-dialect] / src / main / java / de / juplo / thymeleaf / AbstractSubstituteAttrProcessor.java
index 6274016..09b30d1 100644 (file)
@@ -1,14 +1,20 @@
 package de.juplo.thymeleaf;
 
 
-import org.thymeleaf.Arguments;
-import org.thymeleaf.Configuration;
-import org.thymeleaf.dom.Element;
-import org.thymeleaf.processor.ProcessorResult;
-import org.thymeleaf.processor.attr.AbstractAttrProcessor;
-import org.thymeleaf.standard.expression.IStandardExpression;
-import org.thymeleaf.standard.expression.IStandardExpressionParser;
-import org.thymeleaf.standard.expression.StandardExpressions;
+import java.util.HashMap;
+import java.util.Map;
+import org.thymeleaf.context.ITemplateContext;
+import org.thymeleaf.engine.AttributeName;
+import org.thymeleaf.engine.EngineEventUtils;
+import org.thymeleaf.model.IAttribute;
+import org.thymeleaf.model.ICloseElementTag;
+import org.thymeleaf.model.IModel;
+import org.thymeleaf.model.IModelFactory;
+import org.thymeleaf.model.IProcessableElementTag;
+import org.thymeleaf.model.ITemplateEvent;
+import org.thymeleaf.processor.element.AbstractAttributeModelProcessor;
+import org.thymeleaf.processor.element.IElementModelStructureHandler;
+import org.thymeleaf.templatemode.TemplateMode;
 
 
 /**
@@ -16,74 +22,119 @@ import org.thymeleaf.standard.expression.StandardExpressions;
  *
  * @author kai
  */
-public abstract class AbstractSubstituteAttrProcessor extends AbstractAttrProcessor
+public abstract class AbstractSubstituteAttrProcessor
+    extends
+      AbstractAttributeModelProcessor
 {
   public static final int ATTR_PRECEDENCE = 100;
 
+
+  private final String attributeName;
   private final String substituteName;
 
 
-  public AbstractSubstituteAttrProcessor(String attribute, String substitute)
+  public AbstractSubstituteAttrProcessor(
+      final String prefix,
+      final String attribute,
+      final String substitute
+      )
   {
-    super(attribute);
+    super(
+        TemplateMode.HTML,
+        prefix,
+        null,
+        false,
+        attribute,
+        true,
+        ATTR_PRECEDENCE,
+        false
+        );
+    this.attributeName = attribute;
     this.substituteName = substitute;
   }
 
 
   @Override
-  protected final ProcessorResult processAttribute(
-      Arguments arguments,
-      Element element,
-      String name
+  protected void doProcess(
+      final ITemplateContext context,
+      final IModel model,
+      final AttributeName attributeName,
+      final String attributeValue,
+      final IElementModelStructureHandler handler
       )
   {
-    Configuration configuration = arguments.getConfiguration();
-    IStandardExpressionParser parser =
-        StandardExpressions.getExpressionParser(configuration);
-    String value = element.getAttributeValue(name);
-    IStandardExpression expression =
-        parser.parseExpression(configuration, arguments, value);
-    element.removeAttribute(name);
-    if ((Boolean)expression.execute(configuration, arguments))
+    final IProcessableElementTag element = (IProcessableElementTag) model.get(0);
+    final Object result =
+        EngineEventUtils.computeAttributeExpression(
+            context,
+            element,
+            attributeName,
+            attributeValue
+            )
+            .execute(context);
+
+    if (result == null || !(result instanceof Boolean))
     {
-      // We must not clone the processors, because we remove attributes
-      Element substituteElement =
-          element.cloneElementNodeWithNewName(element, substituteName, false);
-      // Remove attributes, that are not allowed for <span> or <strong>
-      substituteElement.removeAttribute("charset");
-      substituteElement.removeAttribute("th:charset");
-      substituteElement.removeAttribute("coords");
-      substituteElement.removeAttribute("href");
-      substituteElement.removeAttribute("th:href");
-      substituteElement.removeAttribute("hreflang");
-      substituteElement.removeAttribute("th:hreflang");
-      substituteElement.removeAttribute("media");
-      substituteElement.removeAttribute("th:media");
-      substituteElement.removeAttribute("name");
-      substituteElement.removeAttribute("th:name");
-      substituteElement.removeAttribute("rel");
-      substituteElement.removeAttribute("th:rel");
-      substituteElement.removeAttribute("ref");
-      substituteElement.removeAttribute("th:ref");
-      substituteElement.removeAttribute("shape");
-      substituteElement.removeAttribute("target");
-      substituteElement.removeAttribute("th:target");
-      substituteElement.removeAttribute("type");
-      substituteElement.removeAttribute("th:type");
-      // Also remove the title-attribute, because the mouse-over is confusing
-      substituteElement.removeAttribute("title");
-      substituteElement.removeAttribute("th:title");
-      // Replace the element
-      element.clearChildren();
-      element.addChild(substituteElement);
-      element.getParent().extractChild(element);
+      return;
     }
-    return ProcessorResult.OK;
-  }
 
-  @Override
-  public final int getPrecedence()
-  {
-    return ATTR_PRECEDENCE;
+
+    IModelFactory factory = context.getModelFactory();
+
+    if ((Boolean)result)
+    {
+      Map<String, String> attributes = new HashMap<>();
+
+      for (IAttribute attribute : element.getAllAttributes())
+      {
+        String name =
+            attribute
+                .getAttributeDefinition()
+                .getAttributeName()
+                .getAttributeName()
+                .toLowerCase();
+        switch (name)
+        {
+          case "charset":
+          case "coords":
+          case "href":
+          case "hreflang":
+          case "media":
+          case "name":
+          case "rel":
+          case "ref":
+          case "shape":
+          case "target":
+          case "type":
+          // Also remove the title-attribute, because the mouse-over is confusing
+          case "title":
+            break;
+          default:
+            if (name.equals(this.attributeName))
+              continue;
+            attributes.put(attribute.getAttributeCompleteName(), attribute.getValue());
+        }
+      }
+
+      ITemplateEvent tag;
+      tag = factory.createOpenElementTag(substituteName, attributes, null, false);
+      model.replace(0, tag);
+      for (int i = model.size(); i > 0; --i)
+      {
+        tag = model.get(i);
+        if (!(tag instanceof ICloseElementTag))
+          continue;
+        ICloseElementTag close = (ICloseElementTag)tag;
+        if (close.isUnmatched())
+          continue;
+        if (close.getElementCompleteName().equals(element.getElementCompleteName()))
+        {
+          model.replace(i, factory.createCloseElementTag(substituteName, close.isSynthetic(), close.isUnmatched()));
+          break;
+        }
+      }
+    }
+    else
+      model.replace(0, factory.removeAttribute(element, attributeName));
   }
 }