henryyan
12/21/2011 - 7:37 AM

gistfile1.java

package com.runchain.comac.service.template.weekly;



import java.io.FileNotFoundException;

import java.io.IOException;

import java.text.ParseException;

import java.util.ArrayList;

import java.util.Calendar;

import java.util.Date;

import java.util.List;



import org.apache.commons.lang.StringUtils;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.transaction.annotation.Transactional;



import com.runchain.arch.service.ServiceException;

import com.runchain.arch.service.base.BaseService;

import com.runchain.arch.util.date.DateBean;

import com.runchain.arch.util.date.DateUtil;

import com.runchain.arch.util.date.WeekDate;

import com.runchain.comac.entity.template.CustomFieldIndexOfTemplate;

import com.runchain.comac.entity.template.TemplateFieldEntity;

import com.runchain.comac.entity.template.task.GroupTask;

import com.runchain.comac.entity.template.task.OrgTask;

import com.runchain.comac.entity.template.task.TemplateTaskEntity;

import com.runchain.comac.entity.template.weekly.WeeklyTemplateEntity;

import com.runchain.comac.service.account.DeptManager;

import com.runchain.comac.service.journal.DailyWorkLogManager;

import com.runchain.comac.service.template.common.CommonTemplateManager;

import com.runchain.comac.service.template.common.CustomFieldIndexOfTemplateManager;

import com.runchain.comac.util.account.OrganizationUtil;

import com.runchain.comac.util.template.ExcelTemplateData;

import com.runchain.comac.util.template.ExcelTemplateResolve;

import com.runchain.comac.util.template.ProjectType;

import com.runchain.comac.util.template.ReportType;

import com.runchain.comac.util.template.TemplateException;

import com.runchain.comac.util.template.TemplateUtil;



/**

 * 周报模板Service

 * <ul>

 * 	<li>T-模板实体</li>

 * 	<li>TOT-部门和任务项关系</li>

 * 	<li>TT-模板任务项</li>

 * 	<li>TF-模板自定义字段</li>

 * </ul>

 *

 * @author HenryYan

 *

 */

public abstract class WeeklyTemplateService<T extends WeeklyTemplateEntity, TOT extends OrgTask, TT extends TemplateTaskEntity<TT>, TF extends TemplateFieldEntity<T>, GT extends GroupTask>

		extends BaseService {



	@Autowired

	protected DailyWorkLogManager dailyWorkLogManager;



	@Autowired

	protected DeptManager deptManager;

	

	@Autowired

	protected CustomFieldIndexOfTemplateManager indexManager;



	protected Integer year;

	protected Integer week;

	protected Long templateId = null;

	protected String templateFileName;

	protected ExcelTemplateResolve<TT, TOT, TF> resolve;



	/**

	 * 从Excel中导入模板文件到数据库

	 * @param template			新的模板对象

	 * @throws ServiceException	业务相关异常

	 * @throws Exception		系统处理异常

	 */

	@Transactional(rollbackFor = {TemplateException.class, ServiceException.class, Exception.class})

	public void importTemplate(T template) throws TemplateException, ServiceException, Exception {



		// 1、检查模板对象

		checkAndInit(template);



		// 2、解析模板

		templateFileName = TemplateUtil.getTemplateFileBasePath() + "/" + template.getTemplateFileName();

		logger.info("开始验证类型为:{}的模板:{}", getProjectType(), templateFileName);



		resolve = getResolve();



		if (resolve.checkTemplate()) {



			// 3.0 检查指定年份和周次模板是否存在

			T dbTemplate = getTemplateManager().findTemplate(year, week);

			if (dbTemplate != null) {

				throw new ServiceException(year + "年" + week + "周的模板已经存在!");

			}



			// 3.1 根据选择的周次获取周的第一天作为模板生效日期

			WeekDate weekDate = new WeekDate(year);

			DateBean dateBean = weekDate.getDateMap().get(week);

			java.sql.Date effectiveDate = DateUtil.extractSqlDate(dateBean.getStartCalendar());

			template.setEffectiveDate(effectiveDate);



			// 3.2、保存模板对象到数据库

			template.setImportDate(new Date());

			template.setVersion(year + "-" + week);

			getTemplateManager().saveEntity(template);

			templateId = template.getId();



			// 3.3、设置上一版本的模板失效日期为此模板生效日期的前一天

			T preVersionTemplate = getTemplateManager().findPreVersionTemplate(year, week);

			if (preVersionTemplate != null) {

				logger.debug("根据{年={},周={}},查询出上一版本的大客周报模板为:{}", new Object[] { year, week, preVersionTemplate });



				// 设置上一版本的失效日期

				Calendar expiryDateCalendar = Calendar.getInstance();

				expiryDateCalendar.setTime(effectiveDate);

				expiryDateCalendar.add(Calendar.DATE, -1);



				java.sql.Date expiryDate = DateUtil.extractSqlDate(expiryDateCalendar);

				preVersionTemplate.setExpiryDate(expiryDate);

				getTemplateManager().saveEntity(preVersionTemplate);

				logger.debug("设置大客周报模板失效日期为:{},模板对象:{}", expiryDate, preVersionTemplate);

			}

		}



		logger.info("开始解析模板:{}", templateFileName);

		

		// 准备部门ID和部门名称映射

		deptManager.initOrganizations(OrganizationUtil.SUPER_UNIT_ID);

		

		resolve.setTemplateId(template.getId());

		ExcelTemplateData<TT, TF> templateData = resolve.readTemplate();



		// 4.1、保存模板任务项

		List<TT> tasks = (List<TT>) templateData.getTasks();

		getTaskManager().saveEntity(tasks);



		// 4.2、保存部门任务分配

		List<OrgTask> orgTasks = new ArrayList<OrgTask>();

		for (TT task : tasks) {

			List<OrgTask> tempOrgTasks = task.getOrgTasks();

			for (OrgTask orgTask : tempOrgTasks) {

				orgTask.getId().setTaskId(task.getId());

				orgTask.setTaskParentId(task.getParent() == null ? null : task.getParent().getId());

				orgTask.setTemplateId(templateId);

			}

			orgTasks.addAll(tempOrgTasks);

		}

		getOrgTaskManager().saveOrgTasks(orgTasks);



		// 4.3、保存模板自定义字段

		List<TF> fields = (List<TF>) templateData.getFields();



		// 4.4、设置字段对应的模板

		for (TF field : fields) {

			field.setTemplate(template);

		}

		getFieldManager().saveEntity(fields);

		

		// 4.5、保存自定义字段索引位置

		List<CustomFieldIndexOfTemplate> indexs = templateData.getIndexs();

		for (CustomFieldIndexOfTemplate index : indexs) {

			index.setTemplateId(templateId);

			indexManager.saveEntity(index);

		}

		

		// 5、加载任务项信息到内存数据库

		TemplateUtil.initWeeklyTaskMapper(templateId, ProjectType.c919);

		logger.info("导入模板成功:{}", template);



	}



	/**

	 * 获取解析对象

	 * @return	模板解析对象

	 * @throws IOException 读取模板文件时

	 * @throws FileNotFoundException 找不到模板文件时

	 * @see {@link ExcelTemplateResolve#createReaderUsePoi}

	 */

	protected abstract ExcelTemplateResolve<TT, TOT, TF> getResolve() throws FileNotFoundException, IOException;



	/**

	 * 检查模板是否可以被导入

	 * @param year	年份

	 * @param week	月份

	 * @return

	 * @throws ServiceException	业务异常

	 * @throws Exception	系统异常

	 */

	public boolean canImportTemplate(Integer year, Integer week) throws ServiceException, Exception {

		// 1、判断唯一版本

		T template = getTemplateManager().findTemplate(year, week);

		if (template != null) {

			throw new ServiceException("已经存在" + year + "年" + week + "周的模板");

		}

		

		String lastVersion = getTemplateManager().getLastVersion();

		if (StringUtils.isNotBlank(lastVersion)) {

			lastVersion = StringUtils.defaultString(lastVersion).replaceAll("-", "");

			if (StringUtils.isNumeric(lastVersion)) {

				Integer integerLastVersion = new Integer(lastVersion);

				Integer selectYearWeek = new Integer(year + "" + week);

				if (selectYearWeek <= integerLastVersion) {

					throw new ServiceException(year + "年第" + week + "周之后已经存在版本,不可导入。");

				}

			} else {

				throw new Exception("得到的版本不能转换为数字");

			}

		}

		

		// 2、判断是否被日志使用

		Boolean checkTemplateUsedByDailyLog = checkTemplateUsedByDailyLog(year, week);

		if (checkTemplateUsedByDailyLog) {

			throw new ServiceException("此周次已有日志使用了模板,不可覆盖!");

		}

		return true;

	}

	

	/**

	 * 检查模板是否被日志使用

	 * @param year	年份

	 * @param week	月份

	 * @throws ServiceException	业务异常,作为提示信息

	 * @throws ParseException 

	 */

	@Transactional(readOnly = true)

	public Boolean checkTemplateUsedByDailyLog(Integer year, Integer week) throws ServiceException, ParseException {

		T enableTemplate = getTemplateManager().findEnableTemplate(year, week);

		if (enableTemplate == null) {

			logger.debug("没有找到{年={},周={}}可用的的{}周报模板", new Object[] { year, week, getProjectType().name() });

			return false;

		} else {

			java.sql.Date maxLogDate = dailyWorkLogManager.getMaxLogDate(getProjectType(), enableTemplate.getId());

			if (maxLogDate == null) {

				logger.debug("{年={},周={}}{}周报模板未被使用", new Object[] { year, week, getProjectType().name() });

				return false;

			} else {

				WeekDate weekDate = new WeekDate(year);

				DateBean dateBean = weekDate.getDateMap().get(week);

				java.sql.Date startDate = DateUtil.extractSqlDate(dateBean.getStartCalendar());



				if (startDate.getTime() > maxLogDate.getTime()) {

					return false;

				}

				logger.debug("{年={},周={}}{}周报模板被日志使用,最后使用日期:{}", new Object[] { year, week, getProjectType().name(),

						maxLogDate });

				throw new ServiceException("本周已有日志,最后使用日期为:" + maxLogDate);

			}

		}

	}



	/**

	 * 删除模板以及相关联的任务项、自定义字段、部门任务分配

	 * 

	 * @param templateId	模板ID

	 * 

	 * @throws ServiceException	业务异常

	 * @throws Exception		系统异常

	 */

	@Transactional(rollbackFor = {ServiceException.class, Exception.class})

	public void deleteTemplate(Long templateId) throws ServiceException, Exception {



		// 1.1 检查模板是否存在

		T weeklyTemplate = getTemplateManager().getEntity(templateId);

		if (weeklyTemplate == null) {

			throw new ServiceException("模板不存在,模板ID=" + templateId);

		}



		// 1.2、 检查是否可以删除(判断此模板是否被使用)

		java.sql.Date maxLogDate = dailyWorkLogManager.getMaxLogDate(getProjectType(), weeklyTemplate.getId());

		if (maxLogDate != null) {

			throw new ServiceException("此模板已被日志使用,最后使用日期为:" + maxLogDate + ",删除失败!");

		}

		

		// 2.1、删除模板任务项

		getTaskManager().deleteTasks(templateId);



		// 2.2、删除自定义字段

		getFieldManager().deleteFields(templateId);



		// 2.3、删除自定义字段位置信息

		indexManager.delete(templateId, getProjectType(), ReportType.weekly);

		

		// 2.4、删除部门任务分配

		getOrgTaskManager().deleteOrgTasks(templateId);

		

		// 2.5、设置上一个版本的实效日期

		T preVersionTemplate = getTemplateManager().findPreVersionTemplate(weeklyTemplate.getYear(), weeklyTemplate.getWeek());

		if (preVersionTemplate != null) {

			preVersionTemplate.setExpiryDate(null);

			getTemplateManager().saveEntity(preVersionTemplate);

		}



		// 2.6、删除模板对象

		getTemplateManager().deleteEntity(weeklyTemplate);



		// 3、删除内存缓存

		TemplateUtil.cleanWeeklyTemplateTaskMapper(templateId, getProjectType());



	}



	/**

	 * 导入前初始化及检查

	 * @param template	模板对象

	 * @throws ServiceException	业务异常

	 * @throws Exception	系统异常

	 */

	private void checkAndInit(T template) throws ServiceException, Exception {

		if (template == null) {

			throw new Exception("模板对象为空");

		}



		year = template.getYear();

		week = template.getWeek();



		if (year == null) {

			throw new ServiceException("导入模板的年份不能为空");

		}

		if (week == null) {

			throw new ServiceException("导入模板的周次不能为空");

		}

	}

	

	/**

	 * 解析前回调

	 * @param template

	 */

	public abstract void beforeResolve(T template);



	/**

	 * 解析完成后回调

	 * @param template

	 */

	public abstract void resolveComplete(T template);



	/**

	 * 获取模板实体管理类

	 * @return

	 */

	protected abstract CommonTemplateManager<T> getTemplateManager();



	/**

	 * 获取任务实体管理类

	 * @return

	 */

	protected abstract WeeklyTemplateTaskManager<TT> getTaskManager();



	/**

	 * 获取模板自定义字段实体管理类

	 * @return

	 */

	protected abstract WeeklyTemplateFieldManager<TF> getFieldManager();



	/**

	 * 获取部门和任务项的关系实体管理类

	 * @return

	 */

	protected abstract WeeklyTemplateOrgTaskManager<T, TOT, TT, GT> getOrgTaskManager();



	/**

	 * 获取项目类型

	 * @return

	 */

	protected abstract ProjectType getProjectType();



}