X-Git-Url: https://juplo.de/gitweb/?p=juplo-dialect;a=blobdiff_plain;f=src%2Fmain%2Fjava%2Fde%2Fjuplo%2Fthymeleaf%2FAbstractSubstituteAttrProcessor.java;h=09b30d19f865f8f359f44188548e40c1fe44678c;hp=6274016d1a22ba459c641b2ab225797666f6a4fb;hb=06b7d4b23347660006a683f003751b704eb67e6e;hpb=4601dbf1b304a81979bf99dd98de50bf909236ec diff --git a/src/main/java/de/juplo/thymeleaf/AbstractSubstituteAttrProcessor.java b/src/main/java/de/juplo/thymeleaf/AbstractSubstituteAttrProcessor.java index 6274016..09b30d1 100644 --- a/src/main/java/de/juplo/thymeleaf/AbstractSubstituteAttrProcessor.java +++ b/src/main/java/de/juplo/thymeleaf/AbstractSubstituteAttrProcessor.java @@ -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 or - 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 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)); } }