package com.idega.block.article.data.dao.impl;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import com.idega.block.article.data.ArticleEntity;
import com.idega.block.article.data.CategoryEntity;
import com.idega.block.article.data.dao.ArticleDaoTemplate;
import com.idega.block.article.data.dao.CategoryDao;
import com.idega.core.persistence.Param;
import com.idega.core.persistence.Query;
import com.idega.core.persistence.impl.GenericDaoImpl;
import com.idega.util.CoreConstants;
import com.idega.util.ListUtil;
import com.idega.util.StringUtil;
import com.idega.util.expression.ELUtil;
@Transactional(readOnly = false)
public abstract class ArticleDaoTemplateImpl<T extends ArticleEntity> extends GenericDaoImpl implements ArticleDaoTemplate<T> {
@Autowired
private CategoryDao categoryDao;
private CategoryDao getCategoryDao() {
if (categoryDao == null)
ELUtil.getInstance().autowire(this);
return categoryDao;
}
private static Logger LOGGER = Logger.getLogger(ArticleDaoImpl.class.getName());
@Override
public boolean updateArticle(Date timestamp, String uri, Collection<String> categories) {
return updateArticle(timestamp, uri, categories, null);
}
/**
* @see com.idega.block.article.data.dao.ArticleDao#getByUri(String)
*/
@Override
public T getByUri(String uri) {
if (StringUtil.isEmpty(uri)) {
LOGGER.warning("Aricle URI is not provided");
return null;
}
if (uri.startsWith(CoreConstants.WEBDAV_SERVLET_URI))
uri = uri.substring(CoreConstants.WEBDAV_SERVLET_URI.length());
if (uri.endsWith(CoreConstants.SLASH))
uri = uri.substring(0, uri.lastIndexOf(CoreConstants.SLASH));
return getSingleResult(ArticleEntity.GET_BY_URI, getEntityClass(), new Param(ArticleEntity.uriProp, uri));
}
/**
* @see com.idega.block.article.data.dao.ArticleDao#getArticleIdByURI(String)
*/
@Override
public Long getArticleIdByURI(String uri) {
ArticleEntity article = getByUri(uri);
return article == null ? Long.valueOf(-1) : article.getId();
}
/**
* @see com.idega.block.article.data.dao.ArticleDao#delete(String)
*/
@Override
public boolean delete(String uri) {
final T article = getByUri(uri);
if (article == null)
return false;
try {
this.remove(article);
return true;
} catch (Exception e) {
LOGGER.log(Level.WARNING, "Failed to remove article from database: " + article, e);
}
return false;
}
protected abstract Class<T> getEntityClass();
/**
* @see com.idega.block.article.data.dao.ArticleDao#getByCategories(List, String, int)
*/
@Override
public List<T> getByCategories(List<String> categories, String uriFrom, int maxResults) {
Class<T> entityClass = getEntityClass();
String entityName = entityClass.getSimpleName();
StringBuilder inlineQuery = new StringBuilder("SELECT DISTINCT a").append(" FROM ").append(entityName).append(" a");
boolean addedWhere = false;
List<Param> params = new ArrayList<Param>();
if (!ListUtil.isEmpty(categories)) {
inlineQuery.append(" JOIN a.").append(ArticleEntity.categoriesProp).append(" c WHERE " +
"c.").append(CategoryEntity.categoryProp).append(" IN (:").append(ArticleEntity.categoriesProp).append(")");
addedWhere = true;
params.add(new Param(ArticleEntity.categoriesProp, categories));
}
if (!StringUtil.isEmpty(uriFrom)) {
if (addedWhere) {
inlineQuery.append(" AND ");
} else {
inlineQuery.append(" WHERE ");
addedWhere = true;
}
inlineQuery.append("a.").append(ArticleEntity.modificationDateProp).append(" <= (SELECT art." + ArticleEntity.modificationDateProp +
" FROM ArticleEntity art where art.").append(ArticleEntity.uriProp).append(" = :").append(ArticleEntity.uriProp).append(")");
params.add(new Param(ArticleEntity.uriProp, uriFrom));
}
if (addedWhere)
inlineQuery.append(" AND ");
else {
inlineQuery.append(" WHERE ");
addedWhere = true;
}
inlineQuery.append("(a.class = ").append(entityName).append(")");
inlineQuery.append(" ORDER BY a.").append(ArticleEntity.modificationDateProp).append(" DESC");
Query query = this.getQueryInline(inlineQuery.toString());
if (maxResults > 0)
query.setMaxResults(maxResults);
List<T> entities = null;
try {
entities = ListUtil.isEmpty(params) ? query.getResultList(entityClass) : query.getResultList(entityClass, params);
} catch (Exception e) {
LOGGER.log(Level.WARNING, "Error loading entities of type " + getEntityClass().getName() + " by query " + inlineQuery.toString(), e);
}
return entities;
}
@Override
public boolean updateArticle(Date timestamp, String uri, Collection<String> categories, Collection<Integer> editors) {
if (timestamp == null || StringUtil.isEmpty(uri)) {
LOGGER.warning("Can not create or update article because URI (" + uri + ") and/or modification date (" + timestamp +
") are not provided!");
return false;
}
// Checking if all categories exist in DB
if (!ListUtil.isEmpty(categories))
getCategoryDao().addCategories(categories);
// Editing or creating
ArticleEntity articleEntity = getByUri(uri);
if (articleEntity == null)
articleEntity = new ArticleEntity();
// Setting specific categories for the article
List<CategoryEntity> categoriesForTheArticle = getCategoryDao().getCategories(categories);
if (!ListUtil.isEmpty(categoriesForTheArticle))
articleEntity.setCategories(categoriesForTheArticle);
// URI
articleEntity.setUri(uri);
// Timestamp
articleEntity.setModificationDate(timestamp);
// Editors
if (!ListUtil.isEmpty(editors))
articleEntity.setEditors(new HashSet<Integer>(editors));
articleEntity = updateArticle(articleEntity);
return articleEntity != null && articleEntity.getId() != null;
}
public <E extends ArticleEntity> E updateArticle(E article) {
if (article == null) {
getLogger().warning("Entity is not provided");
return null;
}
boolean editing = article.getId() != null;
try {
if (editing) {
article = merge(article);
} else {
persist(article);
}
boolean failure = article == null || article.getId() == null;
if (failure) {
getLogger().warning("Unable to " + (editing ? "edit" : "create") + " article: " + article);
return null;
}
return article;
} catch (Exception e) {
LOGGER.log(Level.WARNING, "Failed to " + (editing ? "edit" : "create") + " article " + article, e);
}
return null;
}
@Override
public void remove(T articleEntity) {
if (articleEntity == null)
return;
Long id = articleEntity.getId();
if (id == null)
return;
Class<T> entityClass = getEntityClass();
String entityName = entityClass.getSimpleName();
StringBuilder inlineQuery = new StringBuilder("SELECT a FROM ").append(entityName).append(" a WHERE id = :").append(ArticleEntity.idProp);
Query query = this.getQueryInline(inlineQuery.toString());
List<T> entities = query.getResultList(entityClass, new Param(ArticleEntity.idProp, id));
if (ListUtil.isEmpty(entities))
return;
for (T entity : entities)
super.remove(entity);
}
@Override
public List<CategoryEntity> getCategories(Long articleId) {
Class<T> entityClass = getEntityClass();
String entityName = entityClass.getSimpleName();
StringBuilder inlineQuery =
new StringBuilder("SELECT c FROM ").append(entityName).append(" a join a.categories c WHERE a.id = :").append(ArticleEntity.idProp);
Query query = this.getQueryInline(inlineQuery.toString());
List<CategoryEntity> results = query.getResultList(CategoryEntity.class,new Param(ArticleEntity.idProp,articleId));
return results;
}
}