/*
* =============================================================================
*
* 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.templateparser.markup;
import java.util.concurrent.ConcurrentHashMap;
import org.attoparser.select.IMarkupSelectorReferenceResolver;
import org.thymeleaf.util.Validate;
/**
*
* @author Daniel Fernández
* @since 3.0.0
*
*/
final class TemplateFragmentMarkupReferenceResolver implements IMarkupSelectorReferenceResolver {
private static final TemplateFragmentMarkupReferenceResolver HTML_INSTANCE_NO_PREFIX;
private static final ConcurrentHashMap<String,TemplateFragmentMarkupReferenceResolver> HTML_INSTANCES_BY_PREFIX;
private static final TemplateFragmentMarkupReferenceResolver XML_INSTANCE_NO_PREFIX;
private static final ConcurrentHashMap<String,TemplateFragmentMarkupReferenceResolver> XML_INSTANCES_BY_PREFIX;
private static final String HTML_FORMAT_WITHOUT_PREFIX =
"/[ref='%1$s' or data-ref='%1$s' or fragment='%1$s' or data-fragment='%1$s' or fragment^='%1$s(' or data-fragment^='%1$s(' or fragment^='%1$s (' or data-fragment^='%1$s (']";
private static final String HTML_FORMAT_WITH_PREFIX =
"/[%1$s:ref='%%1$s' or data-%1$s-ref='%%1$s' or %1$s:fragment='%%1$s' or data-%1$s-fragment='%%1$s' or %1$s:fragment^='%%1$s(' or data-%1$s-fragment^='%%1$s(' or %1$s:fragment^='%%1$s (' or data-%1$s-fragment^='%%1$s (']";
private static final String XML_FORMAT_WITHOUT_PREFIX =
"/[ref='%1$s' or fragment='%1$s' or fragment^='%1$s(' or fragment^='%1$s (']";
private static final String XML_FORMAT_WITH_PREFIX =
"/[%1$s:ref='%%1$s' or %1$s:fragment='%%1$s' or %1$s:fragment^='%%1$s(' or %1$s:fragment^='%%1$s (']";
private final ConcurrentHashMap<String,String> selectorsByReference = new ConcurrentHashMap<String, String>(20);
private final String resolverFormat;
static{
HTML_INSTANCE_NO_PREFIX = new TemplateFragmentMarkupReferenceResolver(true, null);
XML_INSTANCE_NO_PREFIX = new TemplateFragmentMarkupReferenceResolver(false, null);
HTML_INSTANCES_BY_PREFIX = new ConcurrentHashMap<String, TemplateFragmentMarkupReferenceResolver>(3, 0.9f, 2);
XML_INSTANCES_BY_PREFIX = new ConcurrentHashMap<String, TemplateFragmentMarkupReferenceResolver>(3, 0.9f, 2);
}
static TemplateFragmentMarkupReferenceResolver forPrefix(final boolean html, final String standardDialectPrefix) {
return html? forHTMLPrefix(standardDialectPrefix) : forXMLPrefix(standardDialectPrefix);
}
private static TemplateFragmentMarkupReferenceResolver forHTMLPrefix(final String standardDialectPrefix) {
if (standardDialectPrefix == null || standardDialectPrefix.length() == 0) {
return HTML_INSTANCE_NO_PREFIX;
}
final String prefix = standardDialectPrefix.toLowerCase();
final TemplateFragmentMarkupReferenceResolver resolver = HTML_INSTANCES_BY_PREFIX.get(prefix);
if (resolver != null) {
return resolver;
}
final TemplateFragmentMarkupReferenceResolver newResolver =
new TemplateFragmentMarkupReferenceResolver(true, prefix);
HTML_INSTANCES_BY_PREFIX.putIfAbsent(prefix, newResolver);
return HTML_INSTANCES_BY_PREFIX.get(prefix);
}
private static TemplateFragmentMarkupReferenceResolver forXMLPrefix(final String standardDialectPrefix) {
if (standardDialectPrefix == null || standardDialectPrefix.length() == 0) {
return XML_INSTANCE_NO_PREFIX;
}
final TemplateFragmentMarkupReferenceResolver resolver = XML_INSTANCES_BY_PREFIX.get(standardDialectPrefix);
if (resolver != null) {
return resolver;
}
final TemplateFragmentMarkupReferenceResolver newResolver =
new TemplateFragmentMarkupReferenceResolver(false, standardDialectPrefix);
XML_INSTANCES_BY_PREFIX.putIfAbsent(standardDialectPrefix, newResolver);
return XML_INSTANCES_BY_PREFIX.get(standardDialectPrefix);
}
private TemplateFragmentMarkupReferenceResolver(final boolean html, final String standardDialectPrefix) {
super();
if (standardDialectPrefix == null) {
this.resolverFormat = (html? HTML_FORMAT_WITHOUT_PREFIX : XML_FORMAT_WITHOUT_PREFIX);
} else {
this.resolverFormat =
(html? String.format(HTML_FORMAT_WITH_PREFIX, standardDialectPrefix) :
String.format(XML_FORMAT_WITH_PREFIX, standardDialectPrefix));
}
}
public String resolveSelectorFromReference(final String reference) {
Validate.notNull(reference, "Reference cannot be null");
final String selector = this.selectorsByReference.get(reference);
if (selector != null) {
return selector;
}
final String newSelector = String.format(this.resolverFormat, reference);
this.selectorsByReference.put(reference, newSelector);
return newSelector;
}
}