/*
* Copyright 2014 Attila Szegedi, Daniel Dekany, Jonathan Revusky
*
* 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 freemarker.cache;
import java.io.IOException;
import freemarker.core.TemplateConfigurer;
import freemarker.template.Configuration;
import freemarker.template.utility.StringUtil;
/**
* Returns the first non-{@code null} result of the child factories, ignoring all further child factories. The child
* factories are called in the order as they were added.
*/
public class FirstMatchTemplateConfigurerFactory extends TemplateConfigurerFactory {
private final TemplateConfigurerFactory[] templateConfigurerFactories;
private boolean allowNoMatch;
private String noMatchErrorDetails;
public FirstMatchTemplateConfigurerFactory(TemplateConfigurerFactory... templateConfigurerFactories) {
this.templateConfigurerFactories = templateConfigurerFactories;
}
@Override
public TemplateConfigurer get(String sourceName, Object templateSource)
throws IOException, TemplateConfigurerFactoryException {
for (TemplateConfigurerFactory tcf : templateConfigurerFactories) {
TemplateConfigurer tc = tcf.get(sourceName, templateSource);
if (tc != null) {
return tc;
}
}
if (!allowNoMatch) {
throw new TemplateConfigurerFactoryException(
FirstMatchTemplateConfigurerFactory.class.getSimpleName()
+ " has found no matching choice for source name "
+ StringUtil.jQuote(sourceName) + ". "
+ (noMatchErrorDetails != null
? "Error details: " + noMatchErrorDetails
: "(Set the noMatchErrorDetails property of the factory bean to give a more specific error "
+ "message. Set allowNoMatch to true if this shouldn't be an error.)"));
}
return null;
}
/**
* Getter pair of {@link #setAllowNoMatch(boolean)}.
*/
public boolean getAllowNoMatch() {
return allowNoMatch;
}
/**
* Use this to specify if having no matching choice is an error. The default is {@code false}, that is, it's an
* error if there was no matching choice.
*
* @see #setNoMatchErrorDetails(String)
*/
public void setAllowNoMatch(boolean allowNoMatch) {
this.allowNoMatch = allowNoMatch;
}
/**
* Use this to specify the text added to the exception error message when there was no matching choice.
* The default is {@code null} (no error details).
*
* @see #setAllowNoMatch(boolean)
*/
public String getNoMatchErrorDetails() {
return noMatchErrorDetails;
}
public void setNoMatchErrorDetails(String noMatchErrorDetails) {
this.noMatchErrorDetails = noMatchErrorDetails;
}
/**
* Same as {@link #setAllowNoMatch(boolean)}, but return this object to support "fluent API" style.
*/
public FirstMatchTemplateConfigurerFactory allowNoMatch(boolean allow) {
setAllowNoMatch(allow);
return this;
}
/**
* Same as {@link #setNoMatchErrorDetails(String)}, but return this object to support "fluent API" style.
*/
public FirstMatchTemplateConfigurerFactory noMatchErrorDetails(String message) {
setNoMatchErrorDetails(message);
return this;
}
@Override
protected void setConfigurationOfChildren(Configuration cfg) {
for (TemplateConfigurerFactory templateConfigurerFactory : templateConfigurerFactories) {
templateConfigurerFactory.setConfiguration(cfg);
}
}
}