/* * ============================================================================= * * Copyright (c) 2011-2016, The THYMELEAF team (http://www.thymeleaf.org) * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * ============================================================================= */ package org.thymeleaf.processor.element; import org.thymeleaf.engine.AttributeName; import org.thymeleaf.engine.HTMLAttributeName; import org.thymeleaf.engine.TextAttributeName; import org.thymeleaf.engine.XMLAttributeName; import org.thymeleaf.templatemode.TemplateMode; import org.thymeleaf.util.TextUtils; import org.thymeleaf.util.Validate; /** * <p> * This class models the way in which an {@link IElementProcessor} can match an element by one of * its attributes. * </p> * <p> * It allows the definition of a matching for a specific attribute with a specific prefix (usually that * of the dialect including the processor), for every attribute with a specific prefix, and also for * simply every attribute. * </p> * <p> * Objects of this class are normally built by the constructors of the processors or their extended abstract * processor classes. * </p> * * @author Daniel Fernández * @since 3.0.0 * */ public final class MatchingAttributeName { private final TemplateMode templateMode; private final AttributeName matchingAttributeName; private final String matchingAllAttributesWithPrefix; private final boolean matchingAllAttributes; public static MatchingAttributeName forAttributeName(final TemplateMode templateMode, final AttributeName matchingAttributeName) { Validate.notNull(templateMode, "Template mode cannot be null"); Validate.notNull(matchingAttributeName, "Matching attribute name cannot be null"); if (templateMode == TemplateMode.HTML && !(matchingAttributeName instanceof HTMLAttributeName)) { throw new IllegalArgumentException("Attribute names for HTML template mode must be of class " + HTMLAttributeName.class.getName()); } else if (templateMode == TemplateMode.XML && !(matchingAttributeName instanceof XMLAttributeName)) { throw new IllegalArgumentException("Attribute names for XML template mode must be of class " + XMLAttributeName.class.getName()); } else if (templateMode.isText() && !(matchingAttributeName instanceof TextAttributeName)) { throw new IllegalArgumentException("Attribute names for any text template modes must be of class " + TextAttributeName.class.getName()); } return new MatchingAttributeName(templateMode, matchingAttributeName, null, false); } public static MatchingAttributeName forAllAttributesWithPrefix(final TemplateMode templateMode, final String matchingAllAttributesWithPrefix) { Validate.notNull(templateMode, "Template mode cannot be null"); // Prefix can actually be null -> match all attributes with no prefix return new MatchingAttributeName(templateMode, null, matchingAllAttributesWithPrefix, false); } public static MatchingAttributeName forAllAttributes(final TemplateMode templateMode) { Validate.notNull(templateMode, "Template mode cannot be null"); return new MatchingAttributeName(templateMode, null, null, true); } private MatchingAttributeName( final TemplateMode templateMode, final AttributeName matchingAttributeName, final String matchingAllAttributesWithPrefix, final boolean matchingAllAttributes) { super(); this.templateMode = templateMode; this.matchingAttributeName = matchingAttributeName; this.matchingAllAttributesWithPrefix = matchingAllAttributesWithPrefix; this.matchingAllAttributes = matchingAllAttributes; } public TemplateMode getTemplateMode() { return this.templateMode; } public AttributeName getMatchingAttributeName() { return this.matchingAttributeName; } public String getMatchingAllAttributesWithPrefix() { return this.matchingAllAttributesWithPrefix; } public boolean isMatchingAllAttributes() { return this.matchingAllAttributes; } public boolean matches(final AttributeName attributeName) { Validate.notNull(attributeName, "Attributes name cannot be null"); if (this.matchingAttributeName == null) { if (this.templateMode == TemplateMode.HTML && !(attributeName instanceof HTMLAttributeName)) { return false; } else if (this.templateMode == TemplateMode.XML && !(attributeName instanceof XMLAttributeName)) { return false; } else if (this.templateMode.isText() && !(attributeName instanceof TextAttributeName)) { return false; } if (this.matchingAllAttributes) { return true; } if (this.matchingAllAttributesWithPrefix == null) { return attributeName.getPrefix() == null; } final String attributeNamePrefix = attributeName.getPrefix(); if (attributeNamePrefix == null) { return false; // we already checked we are not matching nulls } return TextUtils.equals(this.templateMode.isCaseSensitive(), this.matchingAllAttributesWithPrefix, attributeNamePrefix); } return this.matchingAttributeName.equals(attributeName); } @Override public String toString() { if (this.matchingAttributeName == null) { if (this.matchingAllAttributes) { return "*"; } if (this.matchingAllAttributesWithPrefix == null) { return "[^:]*"; } return this.matchingAllAttributesWithPrefix + ":*"; } return matchingAttributeName.toString(); } }