package org.docbag.template.repo;
import java.io.IOException;
import java.util.Collection;
import java.util.concurrent.ConcurrentHashMap;
import org.docbag.DocumentCreatorException;
import org.docbag.template.CachedDocumentTemplateStream;
import org.docbag.template.DocumentTemplateStream;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Iterates through all the registered {@link DocumentTemplateRepository} and uses them to find a
* concrete {@link DocumentTemplateStream}.
* <p>Once a concrete {@link DocumentTemplateRepository} returns a valid {@link DocumentTemplateStream} the iteration process
* ends.</p>
* <p>If the template is found it is stored and cached for later usage. If the template is not found then null is returned.</p>
*
* <p>This class is tread safe.</p>
*
* @author Jakub Torbicki
*/
public class CachingDocumentTemplateRepository implements DocumentTemplateRepository<DocumentTemplateStream> {
private static final String REPOSITORY_NAME = "CachingDocumentTemplateRepository";
private static final Logger log = LoggerFactory.getLogger(CachingDocumentTemplateRepository.class);
private final ConcurrentHashMap<String, CachedDocumentTemplateStream> templates
= new ConcurrentHashMap<String, CachedDocumentTemplateStream>();
private final ConcurrentHashMap<String, DocumentTemplateRepository<DocumentTemplateStream>> finders
= new ConcurrentHashMap<String, DocumentTemplateRepository<DocumentTemplateStream>>();
/**
* Register new {@link DocumentTemplateRepository}
*
* @param finder DocumentTemplateRepository
* @return true if the finder was registered
* false if there was already an instance of DocumentTemplateRepository
* registered with the same {@link Class}
*/
public boolean registerRepository(DocumentTemplateRepository<DocumentTemplateStream> finder) {
String repositoryName = finder.getRepositoryName();
DocumentTemplateRepository<DocumentTemplateStream> repo = finders.get(repositoryName);
if (repo == null) {
repo = finders.putIfAbsent(repositoryName, finder);
if (repo == null) {
return true;
}
}
return false;
}
/**
* Find and cache {@link DocumentTemplateStream}
*
* @param name template's name
* @return {@link DocumentTemplateStream} if found
* null if not found
*/
public DocumentTemplateStream findTemplate(String name) {
if (name == null) {
throw new NullPointerException("Template name can't be null!");
}
CachedDocumentTemplateStream documentTemplate = templates.get(name);
if (documentTemplate == null) {
CachedDocumentTemplateStream document = createDocumentTemplate(name);
if (document != null) {
documentTemplate = templates.putIfAbsent(name, document);
if (documentTemplate == null) {
documentTemplate = document;
}
}
}
return documentTemplate;
}
public String getRepositoryName() {
return REPOSITORY_NAME;
}
private CachedDocumentTemplateStream createDocumentTemplate(String name) {
try {
Collection<DocumentTemplateRepository<DocumentTemplateStream>> finders = this.finders.values();
for (DocumentTemplateRepository<DocumentTemplateStream> finder : finders) {
DocumentTemplateStream docTemplateStream = finder.findTemplate(name);
if (docTemplateStream != null) {
return CachedDocumentTemplateStream.newInstance(docTemplateStream);
}
}
} catch (IOException e) {
log.error("Couldn't create DocumentTemplate", e.getLocalizedMessage(), e);
throw new DocumentCreatorException("Couldn't create DocumentTemplate: ", e);
}
return null;
}
}