WIP:Ported app to Thymeleaf 3.0.x
[juplo-dialect] / src / main / java / de / juplo / thymeleaf / AbstractSubstituteAttributeProcessor.java
diff --git a/src/main/java/de/juplo/thymeleaf/AbstractSubstituteAttributeProcessor.java b/src/main/java/de/juplo/thymeleaf/AbstractSubstituteAttributeProcessor.java
new file mode 100644 (file)
index 0000000..e10365b
--- /dev/null
@@ -0,0 +1,123 @@
+package de.juplo.thymeleaf;
+
+
+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.IStandardExpressionParser;
+import org.thymeleaf.standard.expression.NoOpToken;
+import org.thymeleaf.standard.expression.StandardExpressionExecutionContext;
+import org.thymeleaf.standard.expression.StandardExpressions;
+import org.thymeleaf.templatemode.TemplateMode;
+
+
+/**
+ * Subsitutes the element, that is marked with this attribute-processor.
+ *
+ * @author kai
+ */
+public abstract class AbstractSubstituteAttributeProcessor extends AbstractAttributeTagProcessor
+{
+  public static final int ATTR_PRECEDENCE = 100;
+
+  private final String substituteName;
+
+
+  public AbstractSubstituteAttributeProcessor(String prefix, String attribute, String substitute)
+  {
+    super(TemplateMode.HTML, prefix, null, false, attribute, true, ATTR_PRECEDENCE, true);
+    this.substituteName = substitute;
+  }
+
+
+  @Override
+  protected void doProcess(
+      final ITemplateContext context,
+      final IProcessableElementTag element,
+      final AttributeName name,
+      final String attribute,
+      final IElementTagStructureHandler handler
+      )
+  {
+    if (attribute == null)
+      return;
+
+    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);
+    }
+
+    handler.removeAttribute(name);
+
+    // If the result of this expression is NO-OP, there is nothing to execute
+    if (result == NoOpToken.VALUE)
+      return;
+
+    if ((Boolean)result)
+    {
+      // 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 ProcessorResult.OK;
+  }
+}