blob: 93826566a9ffdc3476e9cb2de5fccdf60573528d [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.TemplateConfiguration;
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 FirstMatchTemplateConfigurationFactory extends TemplateConfigurationFactory {
private final TemplateConfigurationFactory[] templateConfigurationFactories;
private boolean allowNoMatch;
private String noMatchErrorDetails;
public FirstMatchTemplateConfigurationFactory(TemplateConfigurationFactory... templateConfigurationFactories) {
this.templateConfigurationFactories = templateConfigurationFactories;
}
@Override
public TemplateConfiguration get(String sourceName, Object templateSource)
throws IOException, TemplateConfigurationFactoryException {
for (TemplateConfigurationFactory tcf : templateConfigurationFactories) {
TemplateConfiguration tc = tcf.get(sourceName, templateSource);
if (tc != null) {
return tc;
}
}
if (!allowNoMatch) {
throw new TemplateConfigurationFactoryException(
FirstMatchTemplateConfigurationFactory.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 FirstMatchTemplateConfigurationFactory allowNoMatch(boolean allow) {
setAllowNoMatch(allow);
return this;
}
/**
* Same as {@link #setNoMatchErrorDetails(String)}, but return this object to support "fluent API" style.
*/
public FirstMatchTemplateConfigurationFactory noMatchErrorDetails(String message) {
setNoMatchErrorDetails(message);
return this;
}
@Override
protected void setConfigurationOfChildren(Configuration cfg) {
for (TemplateConfigurationFactory templateConfigurationFactory : templateConfigurationFactories) {
templateConfigurationFactory.setConfiguration(cfg);
}
}
}