/**
* Copyright (C) 2015 Born Informatik AG (www.born.ch)
*
* 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.wte4j.persistence;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.NoResultException;
import javax.persistence.OptimisticLockException;
import javax.persistence.PersistenceContext;
import javax.persistence.TypedQuery;
import org.apache.commons.io.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;
import org.wte4j.FileStore;
import org.wte4j.LockingException;
import org.wte4j.Template;
import org.wte4j.TemplateExistException;
import org.wte4j.TemplateQuery;
import org.wte4j.TemplateRepository;
import org.wte4j.User;
import org.wte4j.impl.TemplateContextFactory;
import org.wte4j.impl.WordTemplate;
@Repository
@Transactional("wte4j")
public class WordTemplateRepository implements TemplateRepository {
private Logger logger = LoggerFactory.getLogger(getClass());
@PersistenceContext(unitName = "wte4j-templates")
protected EntityManager em;
@Autowired
protected TemplateContextFactory contextFactory;
@Autowired(required = false)
protected FileStore fileStore;
public WordTemplateRepository() {
}
public WordTemplateRepository(EntityManager em, TemplateContextFactory contextFactory) {
super();
this.em = em;
this.contextFactory = contextFactory;
}
public void setFileStore(FileStore fileStore) {
this.fileStore = fileStore;
}
@Override
public TemplateQuery queryTemplates() {
return new WordTemplateQuery(this, em.getCriteriaBuilder());
}
@Override
public Template<Object> getTemplate(String documentName, String language) {
try {
PersistentTemplate persistentTemplate = getPersistentTemplate(
documentName, language);
return new WordTemplate<Object>(persistentTemplate,
contextFactory);
} catch (NoResultException e) {
return null;
}
}
@Override
public <E> Template<E> getTemplate(String documentName, String language,
Class<? extends E> inputType) throws IllegalArgumentException {
try {
PersistentTemplate persistentTemplate = getPersistentTemplate(
documentName, language);
if (!persistentTemplate.getInputType().isAssignableFrom(inputType)) {
throw new IllegalArgumentException(inputType.getName()
+ " is not suported by the specified template");
}
return new WordTemplate<E>(persistentTemplate,
contextFactory);
} catch (NoResultException e) {
return null;
}
}
private PersistentTemplate getPersistentTemplate(String documentName,
String language) throws NoResultException {
String queryString = "select t from PersistentTemplate t where t.documentName=:documentName "
+ "and t.language= :language";
TypedQuery<PersistentTemplate> query = em.createQuery(queryString,
PersistentTemplate.class);
query.setParameter("documentName", documentName);
query.setParameter("language", language);
return query.getSingleResult();
}
@Override
public <E> Template<E> lockForEdit(Template<E> aTemplate, User user)
throws LockingException {
PersistentTemplate unwrapped = unwrap(aTemplate);
unwrapped.lock(user);
unwrapped = update(unwrapped);
return new WordTemplate<E>(unwrapped, contextFactory);
}
@Override
public <E> Template<E> unlock(Template<E> template) {
PersistentTemplate unwrapped = unwrap(template);
unwrapped.unlock();
unwrapped = update(unwrapped);
return new WordTemplate<E>(unwrapped, contextFactory);
}
@Override
public <E> Template<E> persist(Template<E> toPersist)
throws LockingException {
PersistentTemplate unwrapped = unwrap(toPersist);
if (unwrapped.getId() == null) {
persist(unwrapped);
} else {
unwrapped.unlock();
unwrapped = update(unwrapped);
}
if (isFileStoreSet()) {
updateFileStore(unwrapped);
}
return new WordTemplate<E>(unwrapped, contextFactory);
}
@Override
public void delete(Template<?> template) {
PersistentTemplate unwrapped = unwrap(template);
if (unwrapped.isLocked()) {
throw new LockingException("Template is locked");
}
delete(unwrapped);
if (isFileStoreSet()) {
fileStore.deleteFile(unwrapped.getTemplateFileName());
}
}
private PersistentTemplate unwrap(Template<?> aTemplate) {
WordTemplate<?> wt = (WordTemplate<?>) aTemplate;
if (wt.getTemplateData() instanceof PersistentTemplate) {
return (PersistentTemplate) wt.getTemplateData();
}else{
PersistentTemplate pt = new PersistentTemplate();
pt.setContent(wt.getTemplateData().getContent());
pt.setContentMapping(wt.getContentMapping());
pt.setCreatedAt(wt.getCreatedAt());
pt.setDocumentName(wt.getDocumentName());
pt.setEditedAt(wt.getEditedAt());
pt.setEditor(wt.getEditor());
pt.setInputType(wt.getInputType());
pt.setLanguage(wt.getLanguage());
pt.setProperties(wt.getProperties());
return pt;
}
}
private void persist(PersistentTemplate toPersist) throws LockingException,
TemplateExistException {
if (getTemplate(toPersist.getDocumentName(), toPersist.getLanguage()) != null) {
throw new TemplateExistException("Template with name="
+ toPersist.getDocumentName() + " and language="
+ toPersist.getLanguage() + " allready exists");
}
em.persist(toPersist);
em.flush();
}
private PersistentTemplate update(PersistentTemplate toUpdate) {
try {
PersistentTemplate updated = em.merge(toUpdate);
em.flush();
return updated;
} catch (OptimisticLockException e) {
throw new LockingException("Template has been locked", e);
}
}
private void delete(PersistentTemplate aTemplate) {
try {
PersistentTemplate template = em.merge(aTemplate);
em.remove(template);
em.flush();
} catch (OptimisticLockException e) {
throw new LockingException("Template has been locked", e);
}
}
void updateFileStore(PersistentTemplate template) {
String fileName = template.getTemplateFileName();
try (OutputStream out=fileStore.getOutStream(fileName)) {
IOUtils.write(template.getContent(), out);
} catch (IOException e) {
logger.error("Error occured when storring {}", fileName, e);
}
}
@Transactional
public List<Template<Object>> execute(WordTemplateQuery query) {
List<PersistentTemplate> templates = query.list(em);
List<Template<Object>> wrapped = new ArrayList<Template<Object>>(
templates.size());
for (PersistentTemplate persistentTemplate : templates) {
wrapped.add(new WordTemplate<Object>(persistentTemplate,
contextFactory));
}
return wrapped;
}
boolean isFileStoreSet() {
return fileStore != null;
}
}