WIP:Ported app to Thymeleaf 3.0.x
[juplo-dialect] / src / main / java / de / juplo / thymeleaf / AbstractSubstituteAttributeProcessor.java
1 package de.juplo.thymeleaf;
2
3
4 import org.thymeleaf.context.ITemplateContext;
5 import org.thymeleaf.engine.AttributeName;
6 import org.thymeleaf.engine.EngineEventUtils;
7 import org.thymeleaf.exceptions.TemplateProcessingException;
8 import org.thymeleaf.model.IProcessableElementTag;
9 import org.thymeleaf.processor.element.AbstractAttributeTagProcessor;
10 import org.thymeleaf.processor.element.IElementTagStructureHandler;
11 import org.thymeleaf.standard.expression.FragmentExpression;
12 import org.thymeleaf.standard.expression.FragmentExpression.ExecutedFragmentExpression;
13 import org.thymeleaf.standard.expression.IStandardExpression;
14 import org.thymeleaf.standard.expression.IStandardExpressionParser;
15 import org.thymeleaf.standard.expression.NoOpToken;
16 import org.thymeleaf.standard.expression.StandardExpressionExecutionContext;
17 import org.thymeleaf.standard.expression.StandardExpressions;
18 import org.thymeleaf.templatemode.TemplateMode;
19
20
21 /**
22  * Subsitutes the element, that is marked with this attribute-processor.
23  *
24  * @author kai
25  */
26 public abstract class AbstractSubstituteAttributeProcessor extends AbstractAttributeTagProcessor
27 {
28   public static final int ATTR_PRECEDENCE = 100;
29
30   private final String substituteName;
31
32
33   public AbstractSubstituteAttributeProcessor(String prefix, String attribute, String substitute)
34   {
35     super(TemplateMode.HTML, prefix, null, false, attribute, true, ATTR_PRECEDENCE, true);
36     this.substituteName = substitute;
37   }
38
39
40   @Override
41   protected void doProcess(
42       final ITemplateContext context,
43       final IProcessableElementTag element,
44       final AttributeName name,
45       final String attribute,
46       final IElementTagStructureHandler handler
47       )
48   {
49     if (attribute == null)
50       return;
51
52     final Object result;
53     final IStandardExpression expression =
54        EngineEventUtils.computeAttributeExpression(
55            context,
56            element,
57            name,
58            attribute
59            );
60
61     if (expression != null && expression instanceof FragmentExpression)
62     {
63       final ExecutedFragmentExpression executedFragmentExpression =
64           FragmentExpression.createExecutedFragmentExpression(
65               context,
66               (FragmentExpression) expression,
67               StandardExpressionExecutionContext.NORMAL
68               );
69       result =
70           FragmentExpression.resolveExecutedFragmentExpression(
71               context,
72               executedFragmentExpression,
73               true
74               );
75     }
76     else
77     {
78       result = expression.execute(context);
79     }
80
81     handler.removeAttribute(name);
82
83     // If the result of this expression is NO-OP, there is nothing to execute
84     if (result == NoOpToken.VALUE)
85       return;
86
87     if ((Boolean)result)
88     {
89       // We must not clone the processors, because we remove attributes
90       Element substituteElement =
91           element.cloneElementNodeWithNewName(element, substituteName, false);
92       // Remove attributes, that are not allowed for <span> or <strong>
93       substituteElement.removeAttribute("charset");
94       substituteElement.removeAttribute("th:charset");
95       substituteElement.removeAttribute("coords");
96       substituteElement.removeAttribute("href");
97       substituteElement.removeAttribute("th:href");
98       substituteElement.removeAttribute("hreflang");
99       substituteElement.removeAttribute("th:hreflang");
100       substituteElement.removeAttribute("media");
101       substituteElement.removeAttribute("th:media");
102       substituteElement.removeAttribute("name");
103       substituteElement.removeAttribute("th:name");
104       substituteElement.removeAttribute("rel");
105       substituteElement.removeAttribute("th:rel");
106       substituteElement.removeAttribute("ref");
107       substituteElement.removeAttribute("th:ref");
108       substituteElement.removeAttribute("shape");
109       substituteElement.removeAttribute("target");
110       substituteElement.removeAttribute("th:target");
111       substituteElement.removeAttribute("type");
112       substituteElement.removeAttribute("th:type");
113       // Also remove the title-attribute, because the mouse-over is confusing
114       substituteElement.removeAttribute("title");
115       substituteElement.removeAttribute("th:title");
116       // Replace the element
117       element.clearChildren();
118       element.addChild(substituteElement);
119       element.getParent().extractChild(element);
120     }
121     return ProcessorResult.OK;
122   }
123 }