/* ==================================================================
* Created [2009-4-27 下午11:32:55] by Jon.King
* ==================================================================
* TSS
* ==================================================================
* mailTo:jinpujun@hotmail.com
* Copyright (c) Jon.King, 2009-2012
* ==================================================================
*/
package com.jinhe.tss.cms.service.impl;
import java.io.File;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import com.jinhe.tss.cms.CMSConstants;
import com.jinhe.tss.cms.dao.IArticleDao;
import com.jinhe.tss.cms.dao.IChannelDao;
import com.jinhe.tss.cms.entity.Article;
import com.jinhe.tss.cms.entity.ArticleType;
import com.jinhe.tss.cms.entity.Attachment;
import com.jinhe.tss.cms.entity.Channel;
import com.jinhe.tss.cms.entity.ChannelArticle;
import com.jinhe.tss.cms.entity.ChannelDistribute;
import com.jinhe.tss.cms.entity.ChannelDistributeId;
import com.jinhe.tss.cms.entity.WordsFilter;
import com.jinhe.tss.cms.helper.ArticleHelper;
import com.jinhe.tss.cms.helper.translator.ChannelCanSelectTranslator;
import com.jinhe.tss.cms.helper.translator.ExcludeSiteNodeTranslator;
import com.jinhe.tss.cms.publish.PublishManger;
import com.jinhe.tss.cms.service.IChannelService;
import com.jinhe.tss.component.recycle.RecycleInterceptor;
import com.jinhe.tss.core.exception.BusinessException;
import com.jinhe.tss.core.util.BeanUtil;
import com.jinhe.tss.core.util.EasyUtils;
import com.jinhe.tss.core.web.dispaly.tree.LevelTreeParser;
import com.jinhe.tss.core.web.dispaly.tree.TreeEncoder;
public class ChannelService implements IChannelService {
@Autowired private IChannelDao channelDao;
@Autowired private IArticleDao articleDao;
public List<?> getAllSiteChannelList() {
return channelDao.getAllSiteChannelList();
}
public List<?> getAllChannels() {
String hql = "from Channel c where c.isSite = ? order by c.decode";
return channelDao.getEntities(hql, CMSConstants.FALSE);
}
public Channel getSiteById(Long siteId) {
Channel site = channelDao.getEntity( siteId );
if (site == null) {
throw new BusinessException("您选中站点不存在,可能已经被删除掉了!");
}
return site;
}
public Channel getChannelById(Long id) {
Channel channel = channelDao.getEntity(id);
if (channel == null) {
throw new BusinessException("选择栏目不存在!id = " + id);
}
Long typeId = channel.getArticleTypeId();
if ( typeId != null ) {
ArticleType type = (ArticleType) channelDao.getEntity(ArticleType.class, typeId);
if (type != null) {
channel.setArticleTypeName(type.getName());
}
}
return channel;
}
public Channel createChannel(Channel channel) {
if (CMSConstants.SITE_DEFAULT_NO_RULE.equals(channel.getHotArticleRule()))
channel.setHotArticleRule(CMSConstants.SITE_DEFAULT_HOT_ARTICLE_RULE);
if (CMSConstants.SITE_DEFAULT_NO_RULE.equals(channel.getNewArticleRule()))
channel.setNewArticleRule(CMSConstants.SITE_DEFAULT_NEW_ARTICLE_RULE);
channel.setSeqNo(channelDao.getNextSeqNo(channel.getParentId()));
channel = channelDao.create(channel);
return channel;
}
public Channel updateChannel(Channel channel) {
channelDao.update(channel);
return channel;
}
public Channel createSite(Channel site) {
checkPath(site.getPath(), site.getDocPath(), site.getImagePath());
site.setSeqNo(channelDao.getNextSeqNo(CMSConstants.HEAD_NODE_ID));
site = channelDao.create(site);
return site;
}
public Channel updateSite(Channel site) {
checkPath(site.getPath(), site.getDocPath(), site.getImagePath());
channelDao.update(site);
return site;
}
/** 检测输入路径的正确性 */
private void checkPath(String path, String docPath, String imgPath) {
checkPath(path, "站点的发布路径填写错误,不能生成相应的发布文件路径!");
checkPath(docPath, "站点的附件上传根路径填写错误,不能生成相应的附件上传根路径路径!");
checkPath(imgPath, "站点的图片根路径填写错误,不能生成相应的图片根路径路径!");
}
private void checkPath(String path, String errorMSg){
File file = new File(path);
if (!(file.exists() == true && file.isDirectory() == true && file.canWrite() == true)
&& !(file.exists() == false && file.mkdirs() == true)) {
throw new BusinessException(errorMSg);
}
}
public void deleteChannel(Long channelId) {
if (!checkDownPermission(channelId, CMSConstants.OPERATION_DELETE)) {
throw new BusinessException("您没有删除该栏目的足够权限!");
}
Channel channel = channelDao.getEntity(channelId);
Channel site = channelDao.getSiteByChannel(channelId);
// 先删除栏目下文章
String hql = "select a, ca from Article a, ChannelArticle ca, Channel c " +
" where a.id = ca.id.articleId and ca.id.channelId = c.id and c.decode like ?";
List<?> articleList = channelDao.getEntities(hql, channel.getDecode() + "%");
for ( Object temp : articleList ) {
Object[] objs = (Object[]) temp;
Article article = (Article) objs[0];
ChannelArticle channelArticle = (ChannelArticle) objs[1];
// 相关文章处理(非分发文章),如果是分发文章,则说明文章来自其他栏目,这里不做删除
if ( !CMSConstants.ARTICLE_DISTRIBUTE.equals(channelArticle.getArticleOrigin()) ) {
channelDao.deleteAll(channelDao.getEntities("from ArticleLation o where o.id.articleId = ?", article.getId()));
// 需要绕过回收站拦截器直接物理删除文章,因为栏目已被删除,放入回收站也无意义(无法还原)
RecycleInterceptor.switchTL.set(RecycleInterceptor.SWITCH_CLOSE_TAG);
article.setSite(site);
articleDao.deleteArticle(article);
}
channelDao.delete(channelArticle);
}
// 删除自己和子栏目
List<Channel> subChannels = channelDao.getChildrenById(channelId);
for(Channel temp : subChannels) {
channelDao.deleteById(temp.getId());
}
}
/** 对栏目向下权限的判断: 如果个数不相等,说明用户某些子节点不具有指定的权限 */
protected boolean checkDownPermission(Long resourceId, String operationId) {
List<Channel> rsourceList = channelDao.getChildrenById(resourceId);
List<?> permitedList = channelDao.getChildrenById(resourceId, operationId);
return rsourceList.size() == permitedList.size();
}
public void sortChannel(Long channelId, Long toChannelId, Integer direction) {
channelDao.sort(channelId, toChannelId, direction);
}
public void moveChannel(Long channelId, Long targetId) {
Channel channel = channelDao.getEntity(channelId);
Channel target = channelDao.getEntity(targetId);
channel.setSeqNo(channelDao.getNextSeqNo(targetId));
channel.setParentId(targetId);
channelDao.moveChannel(channel);
List<Channel> children = channelDao.getChildrenById(channelId);
for ( Channel temp : children ) {
temp.setSiteId(target.isSite() ? target.getId() : target.getSiteId());
temp.setDisabled(target.getDisabled());
channelDao.update(temp);
}
}
public List<Channel> copyChannel(Long channelId, Long targetId) {
Channel channel = getChannelById(channelId);
Channel target = channelDao.getEntity(targetId); // 可能为空,复制整站时targetId=-1
Long siteId = null;
List<Channel> returnList = new ArrayList<Channel>();
Map<Long, Long> idsMapping = new HashMap<Long, Long>(); // 维护源节点和复制节点间的映射关系
List<Channel> children = channelDao.getChildrenById(channelId, CMSConstants.OPERATION_VIEW);
for( Channel child : children ){
Channel copyed = new Channel();
BeanUtil.copy(copyed, child);
copyed.setId(null);
if(child.getId().equals(channelId)) {
copyed.setParentId(targetId);
copyed.setSeqNo(channelDao.getNextSeqNo(targetId));
if ( child.getParentId().equals(targetId) ) {
copyed.setName(CMSConstants.COPY_NAME_PREFIX.concat(channel.getName()));
}
}
else {
copyed.setParentId( idsMapping.get(copyed.getParentId()) );
}
copyed = channelDao.create(copyed);
if(target != null) {
siteId = targetId;
copyed.setDisabled(target.getDisabled());
}
else { // target实体不存在,说明是整站复制(即在根节点下的复制),children里第一个节点即为站点
if(copyed.isSite()) {
siteId = copyed.getId();
}
}
copyed.setSiteId(siteId);
idsMapping.put(child.getId(), copyed.getId());
returnList.add(copyed);
}
channelDao.flush();
return returnList;
}
public void stopSite(Long siteOrChannelId) {
if (!checkDownPermission(siteOrChannelId, CMSConstants.OPERATION_STOP)) {
throw new BusinessException("栏目没有停用权限!");
}
List<Channel> list = channelDao.getChildrenById(siteOrChannelId);
for ( Channel child : list ) {
child.setDisabled(CMSConstants.STATUS_STOP);
}
channelDao.flush();
}
public void startSiteAll(Long siteId) {
Channel channel = getSiteById(siteId);
// 启用站点
channel.setDisabled(CMSConstants.STATUS_START);
// 启用站点下栏目
if (channel.isSite()) {
List<?> list = channelDao.getChannelsBySiteIdNoPermission(siteId);
for ( Object entity : list ) {
Channel temp = (Channel) entity;
temp.setDisabled(CMSConstants.STATUS_START);
}
}
channelDao.flush();
}
public void startChannel(Long channelId) {
// 启用所有父亲节点
List<Channel> parents = channelDao.getParentsById(channelId, CMSConstants.OPERATION_START);
for ( Channel parent : parents ) {
parent.setDisabled(CMSConstants.STATUS_START);
}
channelDao.flush();
}
public Object[] selectCanAddArticleParentChannels() {
return selectParentChannelsByOperationId(CMSConstants.OPERATION_ADD_ARTICLE); // 新建文章
}
public Object[] selectCanAddChannelParentChannels() {
return selectParentChannelsByOperationId(CMSConstants.OPERATION_ADD_CHANNEL); // 新建栏目
}
private Object[] selectParentChannelsByOperationId(String operationId) {
List<Long> canAddChannelIds = channelDao.getSiteChannelIDsByOperationId(operationId);
channelDao.insertIds2TempTable( canAddChannelIds );
List<?> channels = channelDao.getParentChannel4CanAdd();
return new Object[]{channels, EasyUtils.list2Str(canAddChannelIds)};
}
public List<Channel> getChannelTreeDown(Long channelId) {
return channelDao.getChildrenById(channelId, CMSConstants.OPERATION_VIEW);
}
public void saveWordsFilter(String shieldWords, String forbidWords, Long siteId) {
channelDao.createObject(new WordsFilter(siteId, shieldWords, forbidWords));
}
public WordsFilter getWordsFilterInfo(Long siteId) {
return (WordsFilter) channelDao.getEntity( WordsFilter.class, siteId);
}
public Object[] getChannelRelationShip(Long channelId) {
List<?> channelList = channelDao.getAllSiteChannelList();
List<?> canAddArticleChannelIds = channelDao.getSiteChannelIDsByOperationId(CMSConstants.OPERATION_ADD_ARTICLE);
String channelIds = EasyUtils.list2Str(canAddArticleChannelIds);
TreeEncoder allTreeEncoder = new TreeEncoder(channelList, new LevelTreeParser());
allTreeEncoder.setTranslator(new ChannelCanSelectTranslator(channelIds, channelId));
allTreeEncoder.setNeedRootNode(false);
List<?> sourceList = channelDao.getChannelSourceByChannelId(channelId);
TreeEncoder fromEncoder = new TreeEncoder(sourceList);
fromEncoder.setRootNodeName("分发自");
fromEncoder.setTranslator(new ExcludeSiteNodeTranslator());
List<?> desList = channelDao.getChannelDestinationByChannelId(channelId);
TreeEncoder toEncoder = new TreeEncoder(desList);
toEncoder.setRootNodeName("分发至");
toEncoder.setTranslator(new ExcludeSiteNodeTranslator());
return new Object[] {allTreeEncoder, fromEncoder, toEncoder};
}
public void saveChannelRelationShip(Long channelId, String distributeFromIds, String distributeToIds) {
// 保存栏目的源栏目信息
channelDao.deleteAll(channelDao.getDistributeFromByChannelId(channelId));
if ( !EasyUtils.isNullOrEmpty(distributeFromIds) ) {
String[] sourceIds = distributeFromIds.split(",");
for (int j = 0; j < sourceIds.length; j++) {
Long sourceId = new Long(sourceIds[j]);
insertChannelDistribute(channelId, sourceId);
}
}
// 保存栏目的目的栏目信息
channelDao.deleteAll(channelDao.getDistributeToByChannelId(channelId));
if ( !EasyUtils.isNullOrEmpty(distributeToIds) ) {
String[] desIds = distributeToIds.split(",");
for (int i = 0; i < desIds.length; i++) {
Long desId = new Long(desIds[i]);
insertChannelDistribute(desId, channelId);
}
}
}
//添加分发栏目
private void insertChannelDistribute(Long channelId, Long distributeFromId) {
ChannelDistributeId channelDistributeId = new ChannelDistributeId();
channelDistributeId.setDistributeToId(channelId);
channelDistributeId.setDistributeFromId(distributeFromId);
ChannelDistribute channelDispatch = new ChannelDistribute();
channelDispatch.setId(channelDistributeId);
channelDao.createObject(channelDispatch);
}
/**************************************************** 以下为栏目(站点)文章发布 *************************************************/
public void publishArticle(List<?> articleIdList, Long siteId) {
// 得到发布路径
Channel site = (Channel)getChannelById(siteId);
// 得到敏感词汇
WordsFilter wordsFilter = (WordsFilter)channelDao.getEntity(WordsFilter.class, siteId);
for (int i = 0; i < articleIdList.size(); i++) {
// 取文章并设置文章属性
Object[] objs = (Object[]) articleIdList.get(i);
// 发布的时候需要把动态属性的字段内容也发布出去
Article article = articleDao.getEntity((Long) objs[0]);
setArticleValue(objs, article);
// 取文章附件列表
Map<String, Attachment> attachments = articleDao.getArticleAttachments(article.getId());
article.getAttachments().putAll(attachments);
// 发布文章,根据文章 创建日期 来设置xml文件的存放路径
String publishPath = site.getPath()+ "/" + ArticleHelper.getArticlePublishRule(article.getCreateTime());
String pubUrl = PublishManger.publishOneArticle(article, publishPath, wordsFilter);
// 设置发布路径保存文章信息
article.setPubUrl(pubUrl);
articleDao.renewArticle(article);
}
}
/**
* 设置文章相关属性,包括文章所属的栏目、文章类型、发布类路径等信息。
*/
private void setArticleValue(Object[] obj, Article article) {
article.setChannelId((Long) obj[1]);
article.setChannelName((String) obj[2]);
article.setTypeName((String) obj[3]);
article.setPublishArticleClassName((String) obj[4]);
article.setStatus(CMSConstants.XML_STATUS);
if (article.getIssueDate() == null || !article.getIssueDate().after(new Date())) {
article.setIssueDate(new Date());
}
}
public int getTotalRows4Publish(Long channelId, String category ) {
return channelDao.getTotalRows4Publish(channelId, category);
}
public List<?> getPageArticleList(Long channelId, int pageNum, int pageSize, String category) {
return channelDao.getPageArticleList4Publish(channelId, category, pageNum, pageSize);
}
public Integer getPublishableArticleCount(Long channelId) {
return channelDao.getPublishableArticleCount(channelId);
}
public List<?> getPagePublishableArticleList(Long channelId, int currentPageNum, Integer pageSize) {
return channelDao.getPagePublishableArticleList(channelId, currentPageNum, pageSize);
}
public Long getSiteIdByChannelId(Long channelId) {
Channel channel = getChannelById(channelId);
return channel.isSite() ? channel.getId() : channel.getSiteId();
}
}