From 06b7d4b23347660006a683f003751b704eb67e6e Mon Sep 17 00:00:00 2001 From: Kai Moritz Date: Wed, 24 Apr 2019 16:27:47 +0200 Subject: [PATCH] TMP --- .../AbstractSubstituteAttrProcessor.java | 171 ++++++++++++------ .../juplo/thymeleaf/ActiveAttrProcessor.java | 6 +- .../thymeleaf/InactiveAttrProcessor.java | 4 +- .../java/de/juplo/thymeleaf/JuploDialect.java | 31 ++-- 4 files changed, 135 insertions(+), 77 deletions(-) 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)); } } diff --git a/src/main/java/de/juplo/thymeleaf/ActiveAttrProcessor.java b/src/main/java/de/juplo/thymeleaf/ActiveAttrProcessor.java index ef17d00..7392bf9 100644 --- a/src/main/java/de/juplo/thymeleaf/ActiveAttrProcessor.java +++ b/src/main/java/de/juplo/thymeleaf/ActiveAttrProcessor.java @@ -6,10 +6,10 @@ package de.juplo.thymeleaf; * marked as active. * @author Kai Moritz */ -public class ActiveAttrProcessor extends AbstractSubstituteAttrProcessor +public class ActiveAttrProcessor extends AbstractSubstituteAttrrocessor { - public ActiveAttrProcessor() + public ActiveAttrProcessor(final String prefix) { - super("active", "strong"); + super(prefix, "active", "strong"); } } diff --git a/src/main/java/de/juplo/thymeleaf/InactiveAttrProcessor.java b/src/main/java/de/juplo/thymeleaf/InactiveAttrProcessor.java index f04074c..6c6ca4b 100644 --- a/src/main/java/de/juplo/thymeleaf/InactiveAttrProcessor.java +++ b/src/main/java/de/juplo/thymeleaf/InactiveAttrProcessor.java @@ -8,8 +8,8 @@ package de.juplo.thymeleaf; */ public class InactiveAttrProcessor extends AbstractSubstituteAttrProcessor { - public InactiveAttrProcessor() + public InactiveAttrProcessor(final String prefix) { - super("inactive", "span"); + super(prefix, "inactive", "span"); } } diff --git a/src/main/java/de/juplo/thymeleaf/JuploDialect.java b/src/main/java/de/juplo/thymeleaf/JuploDialect.java index e4d2d5b..21cf8ac 100644 --- a/src/main/java/de/juplo/thymeleaf/JuploDialect.java +++ b/src/main/java/de/juplo/thymeleaf/JuploDialect.java @@ -2,8 +2,10 @@ package de.juplo.thymeleaf; import java.util.HashSet; +import java.util.Locale; import java.util.Set; -import org.thymeleaf.dialect.AbstractDialect; +import org.springframework.context.MessageSource; +import org.thymeleaf.dialect.AbstractProcessorDialect; import org.thymeleaf.processor.IProcessor; @@ -11,29 +13,34 @@ import org.thymeleaf.processor.IProcessor; * A collection of usefull tools. * @author Kai Moritz */ -public class JuploDialect extends AbstractDialect +public class JuploDialect extends AbstractProcessorDialect { + public static final String DIALECT_NAME = "juplo-Dialect"; public static final String DIALECT_PREFIX = "juplo"; + public static final int DIALECT_PRECEDENCE = 200; - public JuploDialect() - { - super(); - } + final MessageSource messageSource; + final Locale defaultLocale; - @Override - public String getPrefix() + public JuploDialect( + final MessageSource messageSource, + final Locale defaultLocale + ) { - return DIALECT_PREFIX; + super(DIALECT_NAME, DIALECT_PREFIX, DIALECT_PRECEDENCE); + this.messageSource = messageSource; + this.defaultLocale = defaultLocale; } + @Override - public Set getProcessors() + public Set getProcessors(String prefix) { final Set processors = new HashSet<>(); - processors.add(new ActiveAttrProcessor()); - processors.add(new InactiveAttrProcessor()); + processors.add(new ActiveAttributeProcessor(prefix)); + processors.add(new InactiveAttributeProcessor(prefix)); processors.add(new ImportVariablesAttrProcessor()); return processors; } -- 2.20.1