/**
* Copyright 2007-2010 非也
* All rights reserved.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation。
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see http://www.gnu.org/licenses. *
*/
package org.fireflow.engine.modules.persistence.hibernate;
import java.io.ByteArrayInputStream;
import java.io.UnsupportedEncodingException;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.fireflow.engine.entity.repository.ProcessDescriptor;
import org.fireflow.engine.entity.repository.ProcessKey;
import org.fireflow.engine.entity.repository.ProcessRepository;
import org.fireflow.engine.entity.repository.impl.ProcessDescriptorImpl;
import org.fireflow.engine.entity.repository.impl.ProcessRepositoryImpl;
import org.fireflow.engine.modules.persistence.ProcessPersister;
import org.fireflow.engine.modules.processlanguage.ProcessLanguageManager;
import org.fireflow.model.InvalidModelException;
import org.firesoa.common.util.Utils;
import org.hibernate.Hibernate;
import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.SQLQuery;
import org.hibernate.Session;
import org.springframework.orm.hibernate3.HibernateCallback;
/**
*
*
* @author 非也
* @version 2.0
*/
public class ProcessPersisterHibernateImpl extends
AbsPersisterHibernateImpl implements ProcessPersister {
private static final Log log = LogFactory.getLog(ProcessPersisterHibernateImpl.class);
//TODO 下面这个Cache是否需要,待研究……
// process相关的信息实际上已经缓存在KernelManager中了,应该无需保留,此cache机制待删除掉,2013-04-24
Map<ProcessKey,ProcessRepository> cache = new HashMap<ProcessKey,ProcessRepository>();
private boolean useProcessCache = false;
public boolean isUseProcessCache(){
return useProcessCache;
}
public void setUseProcessCache(boolean b){
this.useProcessCache = b;
}
@SuppressWarnings("unchecked")
public Class getEntityClass4Runtime(Class interfaceClz){
if (interfaceClz.isAssignableFrom(ProcessDescriptor.class)){
return ProcessDescriptorImpl.class;
}else if (interfaceClz.isAssignableFrom(ProcessRepository.class)){
return ProcessRepositoryImpl.class;
}
return null;
}
public ProcessDescriptor findProcessDescriptorByProcessKey(
final ProcessKey processKey){
ProcessRepository repository = this.getFromCache(processKey);
if (repository!=null) {
return repository;
}
Object result = this.getHibernateTemplate().execute(new HibernateCallback(){
public Object doInHibernate(Session session)
throws HibernateException, SQLException {
Query q = session.createQuery("from org.fireflow.engine.entity.repository.impl.ProcessDescriptorImpl c where c.processId=:processId and c.processType=:processType and c.version=:version");
q.setString("processId", processKey.getProcessId());
q.setString("processType", processKey.getProcessType());
q.setInteger("version", processKey.getVersion());
return q.uniqueResult();
}
});
return (ProcessDescriptor)result;
}
public String findProcessXml(final ProcessKey processKey){
ProcessRepository repository = this.getFromCache(processKey);
if (repository!=null) {
return repository.getProcessContent();
}
Object result = this.getHibernateTemplate().execute(new HibernateCallback(){
public Object doInHibernate(Session session)
throws HibernateException, SQLException {
Query q = session.createQuery("from org.fireflow.engine.entity.repository.impl.ProcessRepositoryImpl c where c.processId=:processId and c.processType=:processType and c.version=:version");
q.setString("processId", processKey.getProcessId());
q.setString("processType", processKey.getProcessType());
q.setInteger("version", processKey.getVersion());
return q.uniqueResult();
}
});
repository = (ProcessRepository)result;
if (repository!=null){
return repository.getProcessContent();
}
return "";
}
/* (non-Javadoc)
* @see org.fireflow.engine.persistence.ProcessRepositoryPersister#findProcessRepositoryByProcessKey(org.fireflow.engine.entity.repository.ProcessKey)
*/
public ProcessRepository findProcessRepositoryByProcessKey(
final ProcessKey processKey) throws InvalidModelException{
ProcessRepository repository = this.getFromCache(processKey);
if (repository!=null) {
return repository;
}
Object result = this.getHibernateTemplate().execute(new HibernateCallback(){
public Object doInHibernate(Session session)
throws HibernateException, SQLException {
Query q = session.createQuery("from org.fireflow.engine.entity.repository.impl.ProcessRepositoryImpl c where c.processId=:processId and c.processType=:processType and c.version=:version");
q.setString("processId", processKey.getProcessId());
q.setString("processType", processKey.getProcessType());
q.setInteger("version", processKey.getVersion());
return q.uniqueResult();
}
});
repository = (ProcessRepository)result;
if (repository != null) {
try{
ProcessLanguageManager processUtil = persistenceService.getProcessLanguageManager(processKey.getProcessType());
String xml = repository.getProcessContent();
String encoding = Utils.findXmlCharset(xml);
ByteArrayInputStream inStream = new ByteArrayInputStream(xml.getBytes(encoding));
Object obj = processUtil.deserializeXml2Process(inStream);
((ProcessRepositoryImpl)repository).setProcessObject(obj);
//TODO
// repository.getFileName() 与 WorkflowProcess.getClasspathUri()的设置关系如何处理?
}catch(UnsupportedEncodingException e){
log.error(e);
}
}
return repository;
}
/* (non-Javadoc)
* @see org.fireflow.engine.persistence.ProcessRepositoryPersister#findTheLatestVersion(java.lang.String, java.lang.String)
*/
public int findTheLatestVersion(final String processId, final String processType) {
Object result = this.getHibernateTemplate().execute(new HibernateCallback(){
public Object doInHibernate(Session session)
throws HibernateException, SQLException {
Query q = session.createQuery("select max(c.version) from org.fireflow.engine.entity.repository.impl.ProcessDescriptorImpl as c where c.processId=:processId and c.processType=:processType");
// SQLQuery q = session.createSQLQuery("select max(c.version) mxversion from T_FF_DF_PROCESS_REPOSITORY as c where c.process_id=:processId and c.process_type=:processType");
q.setString("processId", processId);
q.setString("processType", processType);
// q.addScalar("mxversion", Hibernate.INTEGER);
Object obj = q.uniqueResult();
return obj;
}
});
if (result==null){
return 0;
}else{
if (result instanceof Integer){
return (Integer)result;
}
else if (result instanceof Long){
return ((Long)result).intValue();
}else{
return 0;
}
}
}
public int findTheLatestPublishedVersion(final String processId,final String processType){
Object result = this.getHibernateTemplate().execute(new HibernateCallback(){
public Object doInHibernate(Session session)
throws HibernateException, SQLException {
Query q = session.createQuery("select max(c.version) from org.fireflow.engine.entity.repository.impl.ProcessDescriptorImpl c where c.processId=:processId and c.processType=:processType and c.publishState=:publishState");
// SQLQuery q = session.createSQLQuery("select max(c.version) maxversion from T_FF_DF_PROCESS_REPOSITORY c where c.process_id=:processId and c.process_type=:processType and c.publish_state=:publishState");
q.setString("processId", processId);
q.setString("processType", processType);
q.setBoolean("publishState", Boolean.TRUE);
// q.addScalar("mxversion", Hibernate.INTEGER);
return q.uniqueResult();
}
});
if (result==null){
return 0;
}else{
if (result instanceof Integer){
return (Integer)result;
}
else if (result instanceof Long){
return ((Long)result).intValue();
}else{
return 0;
}
}
}
/* (non-Javadoc)
* @see org.fireflow.engine.persistence.ProcessRepositoryPersister#findTheLatestVersionOfProcessDescriptor(java.lang.String, java.lang.String)
*/
public ProcessDescriptor findTheLatestVersionOfProcessDescriptor(
String processId, String processType) {
int v = this.findTheLatestVersion(processId,processType) ;
if (v==0){
return null;
}else{
ProcessKey processKey = new ProcessKey(processId,v,processType);
ProcessRepository repository = this.getFromCache(processKey);
if (repository!=null) {
return repository;
}else{
return this.findProcessDescriptorByProcessKey(new ProcessKey(processId,v,processType));
}
}
}
/* (non-Javadoc)
* @see org.fireflow.engine.persistence.ProcessRepositoryPersister#findTheLatestVersionOfProcessRepository(java.lang.String, java.lang.String)
*/
public ProcessRepository findTheLatestVersionOfProcessRepository (
String processId, String processType) throws InvalidModelException{
int v = this.findTheLatestVersion(processId,processType) ;
if (v==0){
return null;
}else{
ProcessKey processKey = new ProcessKey(processId,v,processType);
ProcessRepository repository = this.getFromCache(processKey);
if (repository!=null) {
return repository;
}else{
return this.findProcessRepositoryByProcessKey(new ProcessKey(processId,v,processType));
}
}
}
/* (non-Javadoc)
* @see org.fireflow.engine.modules.persistence.ProcessPersister#persistProcessToRepository(java.lang.Object, java.util.Map)
*/
/*
public ProcessRepository persistProcessToRepository(Object process,
Map<ProcessDescriptorProperty, Object> descriptorKeyValues)throws InvalidModelException {
if (descriptorKeyValues == null){
throw new EngineException("The process metadata can NOT be null");
}
String processType = (String)descriptorKeyValues.get(ProcessDescriptorProperty.PROCESS_TYPE);
if (processType==null || processType.trim().equals("")){
throw new EngineException("The processType can NOT be emtpy!");
}
ProcessLanguageManager processUtil = persistenceService.getProcessUtil(processType);
ProcessRepositoryImpl processRepository = (ProcessRepositoryImpl)processUtil.serializeProcess2ProcessRepository(process);
//1.processType
processRepository.setProcessType(processType);
//2.processId
String processId = (String)descriptorKeyValues.get(ProcessDescriptorProperty.PROCESS_ID);
if (processId == null || processId.trim().equals("")){
processId = processRepository.getProcessId();
if (processId == null || processId.trim().equals("")){
throw new EngineException("The processId can NOT be emtpy!");
}
}else{
processRepository.setProcessId(processId);
}
//3.version
Integer version = (Integer)descriptorKeyValues.get(ProcessDescriptorProperty.VERSION);
ProcessDescriptor existProcess = null;//同一版本的流程是否已经存在。
if (version!=null && version>0){
processRepository.setVersion(version);
existProcess = this.findProcessDescriptorByProcessKey(new ProcessKey(processId,version,processType));
}else{
existProcess = this.findTheLatestVersionOfProcessDescriptor(processId, processType);
if (existProcess==null){
version = 1;
}else{
version = existProcess.getVersion()+1;
}
processRepository.setVersion(version);
}
//4.processName
String processName = (String)descriptorKeyValues.get(ProcessDescriptorProperty.NAME);
if (processName!=null && !processName.trim().equals("")){
processRepository.setName(processName);
}
//5.displayName
String displayName = (String)descriptorKeyValues.get(ProcessDescriptorProperty.DISPLAY_NAME);
if (displayName!=null && !displayName.trim().equals("")){
processRepository.setDisplayName(displayName);
}
//6.description
String description = (String)descriptorKeyValues.get(ProcessDescriptorProperty.DESCRIPTION);
if (description!=null && !description.trim().equals("")){
processRepository.setDescription(description);
}
//7.process
processRepository.setProcessObject(process);
//8.publishState
Boolean publishState = null;
if (existProcess!=null){
publishState = existProcess.getPublishState();
}
Boolean stateFromArgs = null;
if (descriptorKeyValues!=null && descriptorKeyValues
.get(ProcessDescriptorProperty.PUBLISH_STATE)!=null){
if (descriptorKeyValues
.get(ProcessDescriptorProperty.PUBLISH_STATE) instanceof Boolean){
stateFromArgs = (Boolean) descriptorKeyValues
.get(ProcessDescriptorProperty.PUBLISH_STATE);
}
}
publishState = stateFromArgs;
if (publishState==null){
publishState = false;
}
processRepository.setPublishState(publishState);
//9.latestEditor
processRepository.setLastEditor((String) descriptorKeyValues
.get(ProcessDescriptorProperty.LAST_EDITOR));
//10,filename
String fileName = (String) descriptorKeyValues
.get(ProcessDescriptorProperty.FILE_NAME);
if (fileName!=null && !fileName.trim().equals("")){
processRepository.setFileName(fileName);
}else if (existProcess!=null){
//如果已经有现有的Respository,则采用已有的fileName
processRepository.setFileName(existProcess.getFileName());
}
//11.other properties
processRepository.setOwnerDeptId((String) descriptorKeyValues
.get(ProcessDescriptorProperty.OWNER_DEPT_ID));
processRepository.setOwnerDeptName((String) descriptorKeyValues
.get(ProcessDescriptorProperty.OWNER_DEPT_NAME));
processRepository.setApprover((String) descriptorKeyValues
.get(ProcessDescriptorProperty.APPROVER));
processRepository.setApprovedTime((Date) descriptorKeyValues
.get(ProcessDescriptorProperty.APPROVED_TIME));
this.saveOrUpdate(processRepository);
if (useProcessCache){
this.cache(processRepository);
}
return processRepository;
}
*/
// /* (non-Javadoc)
// * @see org.fireflow.engine.persistence.ProcessRepositoryPersister#updateProcessDescriptor(org.fireflow.engine.entity.repository.ProcessDescriptor)
// */
// @Override
// public void updateProcessDescriptor(ProcessDescriptor processDescriptor) {
// this.getHibernateTemplate().update(processDescriptor);
//
// }
// /* (non-Javadoc)
// * @see org.fireflow.engine.persistence.ProcessRepositoryPersister#findAllTheLatestVersionsOfProcessRepository(java.lang.String)
// */
// @Override
// public java.util.List<ProcessRepository> findAllTheLatestVersionsOfProcessRepository(
// String processType) {
// // TODO Auto-generated method stub
// return null;
// }
protected void cache(ProcessRepository processRepository){
if (this.isUseProcessCache()) {
ProcessKey pk = new ProcessKey(processRepository.getProcessId(),
processRepository.getVersion(), processRepository
.getProcessType());
this.cache.put(pk, processRepository);
}
}
protected ProcessRepository getFromCache(ProcessKey key){
if (this.isUseProcessCache()){
return this.cache.get(key);
}
return null;
}
public ProcessRepository persistProcessToRepository(String processXml,ProcessDescriptor descriptor) {
ProcessRepositoryImpl repository = (ProcessRepositoryImpl)descriptor.toProcessRepository();
repository.setProcessContent(processXml);
//表示插入操作,需要重新生成version字段
if (repository.getVersion()==null || repository.getVersion()<=0){
int v = this.findTheLatestVersion(repository.getProcessId(), repository.getProcessType());
repository.setVersion(v+1);
}
this.saveOrUpdate(repository);
//缓存
if (useProcessCache){
this.cache(repository);
}
return repository;
}
/* (non-Javadoc)
* @see org.fireflow.engine.modules.persistence.ProcessPersister#deleteAllProcesses()
*/
public void deleteAllProcesses() {
this.getHibernateTemplate().execute(new HibernateCallback(){
public Object doInHibernate(Session session)
throws HibernateException, SQLException {
String deleteProcessRepository = "Delete From org.fireflow.engine.entity.repository.impl.ProcessRepositoryImpl";
Query q4DeleteProcessRepository = session.createQuery(deleteProcessRepository);
q4DeleteProcessRepository.executeUpdate();
return null;
}
});
}
}