FreeMarkerFirstSupportingTemplateLoader.java
package fr.sii.ogham.template.freemarker;
import java.io.IOException;
import java.io.Reader;
import fr.sii.ogham.core.resource.path.ResolvedResourcePath;
import fr.sii.ogham.core.resource.path.UnresolvedPath;
import fr.sii.ogham.core.resource.resolver.FirstSupportingResourceResolver;
import fr.sii.ogham.core.resource.resolver.ResourceResolver;
import fr.sii.ogham.template.exception.NoResolverAdapterException;
import fr.sii.ogham.template.exception.ResolverAdapterConfigurationException;
import fr.sii.ogham.template.exception.ResolverAdapterException;
import fr.sii.ogham.template.exception.ResolverAdapterNotFoundException;
import fr.sii.ogham.template.freemarker.adapter.FirstSupportingResolverAdapter;
import freemarker.cache.TemplateLoader;
/**
* <p>
* Decorator resolver that is able to manage {@link ResolvedResourcePath}.
* </p>
* <p>
* It delegates to a {@link FirstSupportingResourceResolver} the link between path, {@link ResolvedResourcePath} and {@link ResourceResolver}. each lookup to a
* dedicated {@link ResourceResolver}.
* </p>
* <p>
* It delegates to a {@link FirstSupportingResolverAdapter} the link between {@link ResourceResolver} and the {@link TemplateLoader} implementation to use with
* the given path.
* </p>
*
* @author Cyril Dejonghe
* @see FirstSupportingResourceResolver
* @see FirstSupportingResolverAdapter
*
*/
public class FreeMarkerFirstSupportingTemplateLoader implements TemplateLoader {
private FirstSupportingResourceResolver resolver;
private FirstSupportingResolverAdapter resolverAdapter;
public FreeMarkerFirstSupportingTemplateLoader(FirstSupportingResourceResolver resolver, FirstSupportingResolverAdapter resolverAdapter) {
super();
this.resolver = resolver;
this.resolverAdapter = resolverAdapter;
}
@Override
public Object findTemplateSource(String unresolvedTemplateName) throws IOException {
ResourceResolver supportingResolver = resolver.getSupportingResolver(new UnresolvedPath(unresolvedTemplateName));
TemplateLoader templateLoader;
try {
templateLoader = resolverAdapter.adapt(supportingResolver);
String resolvedPath = supportingResolver.resolve(new UnresolvedPath(unresolvedTemplateName)).getResolvedPath();
Object source = templateLoader.findTemplateSource(resolvedPath);
return source == null ? null : new AdaptedSource(source, templateLoader);
} catch (NoResolverAdapterException e) {
throw new ResolverAdapterNotFoundException("Unable to find template source cause no adapter supporting template name '" + unresolvedTemplateName + "' was found. ", e);
} catch (ResolverAdapterConfigurationException e) {
throw new ResolverAdapterNotFoundException("Unable to find template source because of invalid adapter configuration for template name '" + unresolvedTemplateName + "'. ", e);
} catch (ResolverAdapterException e) {
throw new IOException("Unable to find template source because of adapter failure for template name '" + unresolvedTemplateName + "'. ", e);
}
}
@Override
public long getLastModified(Object templateSource) {
return ((AdaptedSource) templateSource).getLastModified();
}
@Override
public Reader getReader(Object templateSource, String encoding) throws IOException {
return ((AdaptedSource) templateSource).getReader(encoding);
}
@Override
public void closeTemplateSource(Object templateSource) throws IOException {
((AdaptedSource) templateSource).close();
}
/**
* see freemarker.cache.MultiTemplateLoader.MultiSource
*/
static final class AdaptedSource {
private final Object source;
private final TemplateLoader loader;
AdaptedSource(Object source, TemplateLoader loader) {
this.source = source;
this.loader = loader;
}
long getLastModified() {
return loader.getLastModified(source);
}
Reader getReader(String encoding) throws IOException {
return loader.getReader(source, encoding);
}
void close() throws IOException {
loader.closeTemplateSource(source);
}
Object getWrappedSource() {
return source;
}
@Override
public boolean equals(Object o) {
if (o instanceof AdaptedSource) {
AdaptedSource m = (AdaptedSource) o;
return m.loader.equals(loader) && m.source.equals(source);
}
return false;
}
@Override
public int hashCode() {
return loader.hashCode() + 31 * source.hashCode();
}
@Override
public String toString() {
return source.toString();
}
}
}