Source Code Cross Referenced for BpmServiceImpl.java in  » Project-Management » EmForce » org » emforge » jbpm » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Project Management » EmForce » org.emforge.jbpm 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        package org.emforge.jbpm;
0002:
0003:        import java.io.ByteArrayInputStream;
0004:        import java.io.File;
0005:        import java.io.FileNotFoundException;
0006:        import java.io.IOException;
0007:        import java.io.InputStream;
0008:        import java.io.StringWriter;
0009:        import java.io.Writer;
0010:        import java.util.ArrayList;
0011:        import java.util.Collection;
0012:        import java.util.Collections;
0013:        import java.util.Comparator;
0014:        import java.util.Date;
0015:        import java.util.Iterator;
0016:        import java.util.LinkedList;
0017:        import java.util.List;
0018:        import java.util.Map;
0019:        import java.util.zip.ZipInputStream;
0020:
0021:        import javax.jws.WebService;
0022:
0023:        import org.acegisecurity.AccessDeniedException;
0024:        import org.acegisecurity.userdetails.UserDetails;
0025:        import org.apache.commons.collections.CollectionUtils;
0026:        import org.apache.commons.lang.ObjectUtils;
0027:        import org.apache.commons.lang.StringUtils;
0028:        import org.dom4j.DocumentException;
0029:        import org.dom4j.DocumentHelper;
0030:        import org.dom4j.Element;
0031:        import org.dom4j.XPath;
0032:        import org.dom4j.xpath.DefaultXPath;
0033:        import org.emforge.BpmService;
0034:        import org.emforge.EmForgeException;
0035:        import org.emforge.comment.CommentTransformer;
0036:        import org.emforge.jbpm.messages.TaskStatusRequestEmail;
0037:        import org.emforge.jbpm.parser.EmForgeJpdlReader;
0038:        import org.emforge.jbpm.web.bean.WorkflowController;
0039:        import org.emforge.projectmanager.ProjectService;
0040:        import org.emforge.projectmanager.base.MilestoneDO;
0041:        import org.emforge.projectmanager.base.ProjectDO;
0042:        import org.emforge.projectmanager.base.ProjectRole;
0043:        import org.emforge.xfer.CommentTO;
0044:        import org.emforge.xfer.HistoryTO;
0045:        import org.emforge.xfer.PriorityTO;
0046:        import org.emforge.xfer.SelectValueTO;
0047:        import org.emforge.xfer.StepTO;
0048:        import org.emforge.xfer.TaskStatus;
0049:        import org.emforge.xfer.TaskTO;
0050:        import org.emforge.xfer.VariableTO;
0051:        import org.emforge.xfer.WorkflowTO;
0052:        import org.hibernate.Query;
0053:        import org.hibernate.Session;
0054:        import org.jbpm.JbpmContext;
0055:        import org.jbpm.context.def.VariableAccess;
0056:        import org.jbpm.context.exe.ContextInstance;
0057:        import org.jbpm.db.GraphSession;
0058:        import org.jbpm.db.LoggingSession;
0059:        import org.jbpm.file.def.FileDefinition;
0060:        import org.jbpm.graph.def.Action;
0061:        import org.jbpm.graph.def.Event;
0062:        import org.jbpm.graph.def.ProcessDefinition;
0063:        import org.jbpm.graph.exe.Comment;
0064:        import org.jbpm.graph.exe.ProcessInstance;
0065:        import org.jbpm.graph.exe.Token;
0066:        import org.jbpm.graph.log.ProcessStateLog;
0067:        import org.jbpm.logging.exe.LoggingInstance;
0068:        import org.jbpm.logging.log.ProcessLog;
0069:        import org.jbpm.taskmgmt.def.Task;
0070:        import org.jbpm.taskmgmt.exe.SwimlaneInstance;
0071:        import org.jbpm.taskmgmt.exe.TaskInstance;
0072:        import org.jbpm.taskmgmt.exe.TaskMgmtInstance;
0073:        import org.jbpm.taskmgmt.log.TaskAssignLog;
0074:        import org.jbpm.util.ClassLoaderUtil;
0075:        import org.springframework.beans.BeansException;
0076:        import org.springframework.context.ApplicationContext;
0077:        import org.springframework.context.ApplicationContextAware;
0078:        import org.springframework.core.io.Resource;
0079:        import org.springframework.transaction.annotation.Propagation;
0080:        import org.springframework.transaction.annotation.Transactional;
0081:        import org.springmodules.workflow.jbpm31.JbpmCallback;
0082:        import org.springmodules.workflow.jbpm31.JbpmTemplate;
0083:
0084:        import ru.emdev.EmForge.EmForgeContext;
0085:        import ru.emdev.EmForge.email.EmailSender;
0086:        import ru.emdev.EmForge.email.EmailServices;
0087:        import ru.emdev.EmForge.email.EmailerException;
0088:        import ru.emdev.EmForge.security.EmForgeUserDetails;
0089:        import ru.emdev.EmForge.security.UserFactory;
0090:        import ru.emdev.EmForge.security.dao.Role;
0091:        import ru.emdev.EmForge.security.dao.UserDao;
0092:        import ru.emdev.EmForge.security.web.SiteRole;
0093:        import ru.emdev.EmForge.util.Helper;
0094:
0095:        import com.ecyrd.jspwiki.WikiContext;
0096:        import com.ecyrd.jspwiki.WikiEngine;
0097:        import com.ecyrd.jspwiki.WikiException;
0098:        import com.ecyrd.jspwiki.WikiPage;
0099:
0100:        /**
0101:         * Implementation for Bpm Web-Service
0102:         * 
0103:         * @author akakunin
0104:         */
0105:        @WebService(endpointInterface="org.emforge.BpmService")
0106:        @Transactional(propagation=Propagation.REQUIRES_NEW,rollbackFor=EmForgeException.class)
0107:        public class BpmServiceImpl extends JbpmTemplate implements  BpmService,
0108:                ApplicationContextAware {
0109:
0110:            /** Change to Protected as soon as we will remove old classes */
0111:            public static final String COMMENT_FILENAME = "comment.txt";
0112:            protected static final String DATE_SEPARATOR = " date:";
0113:            protected static final String USER_SEPARATOR = " user:";
0114:            protected static final String MESSAGE_SEPARATOR = " message:";
0115:
0116:            private ProjectService projectService;
0117:            private EmForgeContext emForgeContext;
0118:
0119:            // user-factory required to get current user details
0120:            private UserFactory userFactory;
0121:            private UserDao userDao;
0122:
0123:            private EmailServices emailServices;
0124:            private ApplicationContext applicationContext;
0125:
0126:            private Resource initWorkflowsFolder;
0127:
0128:            /**
0129:             * @param i_projectService
0130:             */
0131:            public void setProjectService(ProjectService i_projectService) {
0132:
0133:                projectService = i_projectService;
0134:            }
0135:
0136:            /**
0137:             * @param i_userFactory
0138:             */
0139:            public void setUserFactory(UserFactory i_userFactory) {
0140:
0141:                userFactory = i_userFactory;
0142:            }
0143:
0144:            /**
0145:             * @param i_userDao
0146:             */
0147:            public void setUserDao(UserDao i_userDao) {
0148:
0149:                userDao = i_userDao;
0150:            }
0151:
0152:            /**
0153:             * @param i_emForgeContext
0154:             */
0155:            public void setEmForgeContext(EmForgeContext i_emForgeContext) {
0156:
0157:                emForgeContext = i_emForgeContext;
0158:            }
0159:
0160:            /**
0161:             * @param i_emailServices
0162:             */
0163:            public void setEmailServices(EmailServices i_emailServices) {
0164:
0165:                emailServices = i_emailServices;
0166:            }
0167:
0168:            /**
0169:             * @see org.springframework.context.ApplicationContextAware#setApplicationContext(org.springframework.context.ApplicationContext)
0170:             */
0171:            public void setApplicationContext(
0172:                    ApplicationContext i_applicationContext)
0173:                    throws BeansException {
0174:
0175:                applicationContext = i_applicationContext;
0176:            }
0177:
0178:            /**
0179:             * @param i_initWorkflowsFolder
0180:             */
0181:            public void setInitWorkflowsFolder(Resource i_initWorkflowsFolder) {
0182:
0183:                initWorkflowsFolder = i_initWorkflowsFolder;
0184:            }
0185:
0186:            /**
0187:             * We need to get wikiEngine dinamically, to avoid cyclic references
0188:             * 
0189:             * @return
0190:             */
0191:            private WikiEngine getWikiEngine() {
0192:
0193:                return (WikiEngine) applicationContext.getBean("wikiEngine");
0194:            }
0195:
0196:            /**
0197:             * @see org.springmodules.workflow.jbpm31.JbpmTemplate#afterPropertiesSet()
0198:             */
0199:            @Override
0200:            public void afterPropertiesSet() throws Exception {
0201:
0202:                super .afterPropertiesSet();
0203:
0204:                // check for workflows, included into distribution and try to install them
0205:                if (initWorkflowsFolder != null)
0206:                    try {
0207:                        File directory = null;
0208:
0209:                        try {
0210:                            directory = initWorkflowsFolder.getFile();
0211:                        } catch (FileNotFoundException ex) {
0212:                            // just ignore it here - we simple do not have directory with default processes
0213:                        }
0214:
0215:                        if (directory != null) {
0216:                            String[] files = directory.list();
0217:
0218:                            for (int i = 0; i < files.length; i++) {
0219:                                final String fileName = files[i];
0220:
0221:                                if (fileName.endsWith(".par")) {
0222:                                    final String workflowName = fileName
0223:                                            .substring(0, fileName.length() - 4);
0224:
0225:                                    execute(new JbpmCallback() {
0226:
0227:                                        @SuppressWarnings("unchecked")
0228:                                        public Object doInJbpm(
0229:                                                JbpmContext context) {
0230:
0231:                                            // check is workflow exists
0232:                                            ProcessDefinition processDef = getProcessDef(
0233:                                                    context, workflowName,
0234:                                                    WORKFLOW_LAST_VERSION);
0235:
0236:                                            if (processDef == null) {
0237:                                                // we do not have workflow with specified name
0238:                                                // so - deploy it
0239:                                                InputStream workflowStream = ClassLoaderUtil
0240:                                                        .getStream("processes/"
0241:                                                                + fileName);
0242:
0243:                                                try {
0244:                                                    deployProcessDef(context,
0245:                                                            workflowStream,
0246:                                                            "Installed from distribution");
0247:                                                } catch (IOException ex) {
0248:                                                    logger
0249:                                                            .error(
0250:                                                                    "Cannot deploy workflow: "
0251:                                                                            + workflowName,
0252:                                                                    ex);
0253:                                                    // nothing to do - try to deploy next one
0254:                                                }
0255:                                            }
0256:                                            return null;
0257:                                        }
0258:                                    });
0259:                                }
0260:                            }
0261:                        }
0262:                    } catch (Exception ex) {
0263:                        logger.error("Cannot initialize default workflows", ex);
0264:                    }
0265:            }
0266:
0267:            //
0268:            // web-service implementation
0269:            //
0270:
0271:            /**
0272:             * Returns List of Active Tasks for Logged-In user for Specified Project
0273:             * 
0274:             * @param projectName
0275:             * @return
0276:             */
0277:            @SuppressWarnings("unchecked")
0278:            public List<StepTO> getActiveSteps(String i_projectName)
0279:                    throws EmForgeException {
0280:
0281:                // check - is project exists
0282:                if (!StringUtils.isEmpty(i_projectName)
0283:                        && projectService.getProject(i_projectName) == null) {
0284:                    throw new EmForgeException("Project \"" + i_projectName
0285:                            + "\" not found");
0286:                }
0287:
0288:                // get project
0289:                final ProjectDO project = StringUtils.isEmpty(i_projectName) ? null
0290:                        : projectService.getProject(i_projectName);
0291:
0292:                // get current user
0293:                final UserDetails currentUser = userFactory.getCurrentUser();
0294:
0295:                // get list of active tasks for user
0296:                List<StepTO> steps = (List<StepTO>) execute(new JbpmCallback() {
0297:
0298:                    @SuppressWarnings("unchecked")
0299:                    public Object doInJbpm(JbpmContext context) {
0300:
0301:                        Session session = context.getSession();
0302:                        assert session != null;
0303:
0304:                        Query query = session
0305:                                .getNamedQuery("TaskListBean.findActiveTasks");
0306:                        assert query != null;
0307:
0308:                        if (currentUser != null) {
0309:                            query.setString("actorId", currentUser
0310:                                    .getUsername());
0311:                        } else {
0312:                            query.setString("actorId", "");
0313:                        }
0314:                        Long projectId = (project == null) ? Long.valueOf(-1)
0315:                                : project.getId();
0316:                        query.setParameter("projectId", projectId);
0317:                        List<TaskInstance> activeTasks = query.list();
0318:
0319:                        // create result
0320:                        Collection<StepTO> outputCollection = new StepCollection(
0321:                                activeTasks, new TaskTransformer(
0322:                                        projectService, userFactory));
0323:
0324:                        return outputCollection;
0325:                    }
0326:                });
0327:
0328:                return steps;
0329:            }
0330:
0331:            /**
0332:             * Returns Specific Step by ID
0333:             * 
0334:             * @param stepId - step to return
0335:             * @return step object, or null if nothing found
0336:             */
0337:            public StepTO getStep(final long stepId) throws EmForgeException {
0338:
0339:                StepTO step = (StepTO) execute(new JbpmCallback() {
0340:
0341:                    @SuppressWarnings("unchecked")
0342:                    public Object doInJbpm(JbpmContext context) {
0343:
0344:                        TaskInstance task = context.getTaskInstance(stepId);
0345:
0346:                        if (task == null) {
0347:                            return null;
0348:                        }
0349:
0350:                        return new TaskTransformer(projectService, userFactory)
0351:                                .transform(task);
0352:                    }
0353:                });
0354:
0355:                if (!canReadTask(step.getTaskId())) {
0356:                    throw new AccessDeniedException(
0357:                            "You are not allowed to view this task");
0358:                }
0359:
0360:                return step;
0361:            }
0362:
0363:            /**
0364:             * Returns Specific Task by ID
0365:             * 
0366:             * @param taskId - task to return
0367:             * @return task object, or null if nothing found
0368:             */
0369:            public TaskTO getTask(final long taskId) throws EmForgeException {
0370:
0371:                final ProcessTransformer processTransformer = new ProcessTransformer(
0372:                        this , projectService, userFactory, getWikiEngine(),
0373:                        true);
0374:                TaskTO task = (TaskTO) execute(new JbpmCallback() {
0375:
0376:                    @SuppressWarnings("unchecked")
0377:                    public Object doInJbpm(JbpmContext context) {
0378:
0379:                        ProcessInstance process = context
0380:                                .getProcessInstance(taskId);
0381:
0382:                        if (process == null) {
0383:                            return null;
0384:                        }
0385:
0386:                        return processTransformer.transform(process);
0387:                    }
0388:                });
0389:
0390:                if (task != null && !canReadTask(task.getId())) {
0391:                    throw new AccessDeniedException(
0392:                            "You are not allowed to view this task");
0393:                }
0394:
0395:                return task;
0396:            }
0397:
0398:            /**
0399:             * @see org.emforge.BpmService#hasTask(long)
0400:             */
0401:            public Boolean hasTask(final long taskId) {
0402:
0403:                Boolean hasTask = (Boolean) execute(new JbpmCallback() {
0404:
0405:                    @SuppressWarnings("unchecked")
0406:                    public Object doInJbpm(JbpmContext context) {
0407:
0408:                        ProcessInstance process = context
0409:                                .getProcessInstance(taskId);
0410:
0411:                        if (process == null) {
0412:                            return false;
0413:                        } else {
0414:                            return true;
0415:                        }
0416:                    }
0417:                });
0418:
0419:                return hasTask;
0420:            }
0421:
0422:            /**
0423:             * Return workflow by name and version
0424:             * 
0425:             * @param name - name of workflow
0426:             * @param version - version. If -1 is used - means last version of specified workflow
0427:             * @return Workflow object for specified name and version. Null is not found
0428:             */
0429:            public WorkflowTO getWorkflowByName(final String i_name,
0430:                    final int i_version) throws EmForgeException {
0431:
0432:                WorkflowTO workflow = (WorkflowTO) execute(new JbpmCallback() {
0433:
0434:                    public Object doInJbpm(JbpmContext context) {
0435:
0436:                        ProcessDefinition processDef = getProcessDef(context,
0437:                                i_name, i_version);
0438:
0439:                        if (processDef == null) {
0440:                            return null;
0441:                        }
0442:
0443:                        ProcessDefTransformer processDefTransformer = new ProcessDefTransformer(
0444:                                getWikiEngine(), context);
0445:
0446:                        return processDefTransformer.transform(processDef);
0447:                    }
0448:                });
0449:
0450:                return workflow;
0451:            }
0452:
0453:            /**
0454:             * @see org.emforge.BpmService#hasWorkflow(java.lang.String, int)
0455:             */
0456:            public Boolean hasWorkflow(final String i_name, final int i_version) {
0457:
0458:                Boolean hasWorkflow = (Boolean) execute(new JbpmCallback() {
0459:
0460:                    public Object doInJbpm(JbpmContext context) {
0461:
0462:                        ProcessDefinition processDef = getProcessDef(context,
0463:                                i_name, i_version);
0464:
0465:                        if (processDef == null) {
0466:                            return false;
0467:                        } else {
0468:                            return true;
0469:                        }
0470:                    }
0471:                });
0472:
0473:                return hasWorkflow;
0474:            }
0475:
0476:            /**
0477:             * Return workflow by id
0478:             * 
0479:             * @param workflowId - id of workflow
0480:             * @return Workflow object for specified id. Null is not found
0481:             */
0482:            public WorkflowTO getWorkflowById(final long i_workflowId)
0483:                    throws EmForgeException {
0484:
0485:                WorkflowTO workflow = (WorkflowTO) execute(new JbpmCallback() {
0486:
0487:                    public Object doInJbpm(JbpmContext context) {
0488:
0489:                        ProcessDefinition processDef = context
0490:                                .getGraphSession().getProcessDefinition(
0491:                                        i_workflowId);
0492:
0493:                        if (processDef == null) {
0494:                            return null;
0495:                        }
0496:
0497:                        // convert processDef into workflow
0498:                        ProcessDefTransformer processDefTransformer = new ProcessDefTransformer(
0499:                                getWikiEngine(), context);
0500:
0501:                        return processDefTransformer.transform(processDef);
0502:                    }
0503:                });
0504:
0505:                return workflow;
0506:            }
0507:
0508:            /**
0509:             * Return list of Workflows, stored in the system
0510:             * 
0511:             * @return
0512:             */
0513:            @SuppressWarnings("unchecked")
0514:            public WorkflowTO[] getWorkflows() throws EmForgeException {
0515:
0516:                List<WorkflowTO> workflows = (List<WorkflowTO>) execute(new JbpmCallback() {
0517:
0518:                    public Object doInJbpm(JbpmContext context) {
0519:
0520:                        ProcessDefTransformer processDefTransformer = new ProcessDefTransformer(
0521:                                getWikiEngine(), context);
0522:
0523:                        List<WorkflowTO> workflows = new LinkedList<WorkflowTO>();
0524:
0525:                        /*
0526:                         * List<ProcessDefinition> processDefinitions =
0527:                         * context.getSession().getNamedQuery("ProcessDefListBean.findLastProcessDefinitions").list();
0528:                         */
0529:                        Session dbSession = context.getSession();
0530:                        GraphSession gSession = new GraphSession(dbSession);
0531:                        List<ProcessDefinition> processDefinitions = gSession
0532:                                .findLatestProcessDefinitions();
0533:
0534:                        CollectionUtils.collect(processDefinitions,
0535:                                processDefTransformer, workflows);
0536:
0537:                        // sort workflows by Start Task Name
0538:                        Collections.sort(workflows,
0539:                                new Comparator<WorkflowTO>() {
0540:
0541:                                    public int compare(WorkflowTO workflow1,
0542:                                            WorkflowTO workflow2) {
0543:
0544:                                        if (workflow1 == null
0545:                                                && workflow2 == null) {
0546:                                            return 0;
0547:                                        } else if (workflow1 == null) {
0548:                                            return -1;
0549:                                        } else if (workflow2 == null) {
0550:                                            return 1;
0551:                                        } else {
0552:                                            return workflow1
0553:                                                    .getStartName()
0554:                                                    .compareTo(
0555:                                                            workflow2
0556:                                                                    .getStartName());
0557:                                        }
0558:                                    }
0559:                                });
0560:
0561:                        return workflows;
0562:                    }
0563:                });
0564:
0565:                return workflows.toArray(new WorkflowTO[workflows.size()]);
0566:            }
0567:
0568:            /**
0569:             * Retunrs history for workflow versions
0570:             * 
0571:             * @param name - workflow name to get history
0572:             * @param version - workflow version to get history
0573:             * @return
0574:             * @throws EmForgeException
0575:             */
0576:            public HistoryTO[] getWorkflowHistory(final String i_name,
0577:                    final int i_version) {
0578:
0579:                HistoryTO[] result = (HistoryTO[]) execute(new JbpmCallback() {
0580:
0581:                    @SuppressWarnings("unchecked")
0582:                    public Object doInJbpm(JbpmContext context) {
0583:
0584:                        List<ProcessDefinition> processDefs = context
0585:                                .getGraphSession()
0586:                                .findAllProcessDefinitionVersions(i_name);
0587:                        List<HistoryTO> history = new LinkedList<HistoryTO>();
0588:
0589:                        // transform process defs into history elements
0590:                        CollectionUtils.collect(processDefs,
0591:                                new ProcessDefToHistoryTransformer(
0592:                                        getWikiEngine(), emForgeContext),
0593:                                history);
0594:
0595:                        return history.toArray(new HistoryTO[history.size()]);
0596:                    }
0597:                });
0598:
0599:                return result;
0600:            }
0601:
0602:            /**
0603:             * @see org.emforge.BpmService#getUsedWorkflows(java.lang.String, int)
0604:             */
0605:            public WorkflowTO[] getUsedWorkflows(final String name,
0606:                    final int version) throws EmForgeException {
0607:
0608:                Object result = execute(new JbpmCallback() {
0609:
0610:                    @SuppressWarnings("unchecked")
0611:                    public Object doInJbpm(JbpmContext context) {
0612:
0613:                        ProcessDefinition processDef = getProcessDef(context,
0614:                                name, version);
0615:
0616:                        if (processDef == null) {
0617:                            return new EmForgeException(
0618:                                    "Cannot find specified workflow");
0619:                        }
0620:
0621:                        Session session = context.getSession();
0622:                        assert session != null;
0623:
0624:                        Query query = session
0625:                                .getNamedQuery("JbpmProcessDefImpl.findSubProcesses");
0626:                        assert query != null;
0627:
0628:                        query.setLong("processDefId", processDef.getId());
0629:
0630:                        List<ProcessDefinition> subProcesses = query.list();
0631:
0632:                        // now select all late-binded names
0633:                        query = session
0634:                                .getNamedQuery("JbpmProcessDefImpl.findSubProcessNames");
0635:                        assert query != null;
0636:
0637:                        query.setLong("processDefId", processDef.getId());
0638:                        List<String> lateBindedNames = query.list();
0639:
0640:                        // now add late-binded processDefs into list
0641:                        for (String lateBindedName : lateBindedNames) {
0642:                            boolean found = false;
0643:                            // is it already exists?
0644:                            for (ProcessDefinition subProcDef : subProcesses) {
0645:                                if (subProcDef.equals(lateBindedName)) {
0646:                                    found = true;
0647:                                    break;
0648:                                }
0649:                            }
0650:
0651:                            if (!found) {
0652:                                subProcesses.add(context.getGraphSession()
0653:                                        .findLatestProcessDefinition(
0654:                                                lateBindedName));
0655:                            }
0656:                        }
0657:
0658:                        List<WorkflowTO> workflows = new LinkedList<WorkflowTO>();
0659:                        ProcessDefTransformer transformer = new ProcessDefTransformer(
0660:                                getWikiEngine(), context);
0661:
0662:                        CollectionUtils.collect(subProcesses, transformer,
0663:                                workflows);
0664:
0665:                        return workflows.toArray(new WorkflowTO[workflows
0666:                                .size()]);
0667:                    }
0668:                });
0669:
0670:                if (result instanceof  EmForgeException) {
0671:                    throw (EmForgeException) result;
0672:                }
0673:
0674:                return (WorkflowTO[]) result;
0675:            }
0676:
0677:            /**
0678:             * Returns Blocking Steps for specified Task
0679:             */
0680:            @SuppressWarnings("unchecked")
0681:            public StepTO[] getBlockingSteps(final long i_taskId)
0682:                    throws EmForgeException {
0683:
0684:                if (!canReadTask(i_taskId)) {
0685:                    throw new AccessDeniedException(
0686:                            "You are not allowed to view this task");
0687:                }
0688:
0689:                List<StepTO> blockingSteps = (List<StepTO>) execute(new JbpmCallback() {
0690:
0691:                    @SuppressWarnings("unchecked")
0692:                    public Object doInJbpm(JbpmContext context) {
0693:
0694:                        List<StepTO> result = new LinkedList<StepTO>();
0695:
0696:                        // get process
0697:                        ProcessInstance process = context
0698:                                .getProcessInstance(i_taskId);
0699:
0700:                        if (process == null) {
0701:                            return result;
0702:                        }
0703:
0704:                        // get blocking tasks for process
0705:                        Collection<TaskInstance> blockingTasks = getBlockingTasks(process);
0706:
0707:                        // convert it to StepTO
0708:                        CollectionUtils
0709:                                .collect(blockingTasks, new TaskTransformer(
0710:                                        projectService, userFactory), result);
0711:
0712:                        return result;
0713:                    }
0714:                });
0715:
0716:                return blockingSteps.toArray(new StepTO[blockingSteps.size()]);
0717:            }
0718:
0719:            /**
0720:             * Add comment for specified Task
0721:             * 
0722:             * @return created Comment object
0723:             */
0724:            public Boolean addComment(final long i_taskId,
0725:                    final String i_comment) throws EmForgeException {
0726:
0727:                if (!canCommentTask(i_taskId)) {
0728:                    throw new AccessDeniedException(
0729:                            "You are not allowed to add comment for this task");
0730:                }
0731:
0732:                Boolean result = (Boolean) execute(new JbpmCallback() {
0733:
0734:                    @SuppressWarnings("unchecked")
0735:                    public Object doInJbpm(JbpmContext context) {
0736:
0737:                        if (StringUtils.isNotBlank(i_comment)) {
0738:                            // get process
0739:                            ProcessInstance process = context
0740:                                    .getProcessInstance(i_taskId);
0741:
0742:                            if (process == null) {
0743:                                return false;
0744:                            }
0745:
0746:                            process.getRootToken().addComment(i_comment);
0747:                        }
0748:
0749:                        return true;
0750:                    }
0751:                });
0752:
0753:                return result;
0754:            }
0755:
0756:            /**
0757:             * Returns Comments for Specified Task
0758:             * 
0759:             * @param taskId - id of task we need to get comments
0760:             * @return array of task comments
0761:             */
0762:            @SuppressWarnings("unchecked")
0763:            public CommentTO[] getTaskComments(final long i_taskId)
0764:                    throws EmForgeException {
0765:
0766:                if (!canReadTask(i_taskId)) {
0767:                    throw new AccessDeniedException(
0768:                            "You are not allowed to view this task");
0769:                }
0770:
0771:                List<Comment> comments = (List<Comment>) execute(new JbpmCallback() {
0772:
0773:                    @SuppressWarnings("unchecked")
0774:                    public Object doInJbpm(JbpmContext context) {
0775:
0776:                        List<Comment> result = new ArrayList<Comment>();
0777:
0778:                        // get process
0779:                        ProcessInstance process = context
0780:                                .getProcessInstance(i_taskId);
0781:
0782:                        if (process == null) {
0783:                            return result;
0784:                        }
0785:
0786:                        addComments(process.getRootToken(), result);
0787:
0788:                        // sort comments according to date
0789:                        Collections.sort(result, new Comparator<Comment>() {
0790:
0791:                            public int compare(Comment o1, Comment o2) {
0792:
0793:                                // [AKA] I meet here very stupid exception
0794:                                // seems Timestamp.comparyTo cannot be called with simple Date
0795:                                // as argument
0796:                                // but in my case once it happend (one time was timestamp and
0797:                                // another just date
0798:                                // return o1.getTime().compareTo(o2.getTime());
0799:
0800:                                int value = o2.getTime()
0801:                                        .compareTo(o1.getTime());
0802:
0803:                                if (value > 0) {
0804:                                    return -1;
0805:                                } else if (value < 0) {
0806:                                    return 1;
0807:                                } else {
0808:                                    return 0;
0809:                                }
0810:                            }
0811:                        });
0812:
0813:                        return result;
0814:                    }
0815:                });
0816:
0817:                // now, transform jbpm Comments to CommentTO
0818:                CommentTransformer transformer = new JbpmCommentTransformer(
0819:                        getWikiEngine(), String.valueOf(i_taskId));
0820:                Collection<CommentTO> outputCollection = new LinkedList<CommentTO>();
0821:                CollectionUtils
0822:                        .collect(comments, transformer, outputCollection);
0823:
0824:                // return result
0825:                return outputCollection.toArray(new CommentTO[outputCollection
0826:                        .size()]);
0827:            }
0828:
0829:            /**
0830:             * Add new workflow
0831:             * 
0832:             * @param workflowContent - content of par-file
0833:             * @param comment - comment for this deployment
0834:             * @return create workflow
0835:             */
0836:            public WorkflowTO addNewWorkflow(final byte[] i_workflowContent,
0837:                    final String comment) throws EmForgeException {
0838:
0839:                if (!canAddNewWorkflow()) {
0840:                    throw new AccessDeniedException(
0841:                            "You are not allowed to add workflows");
0842:                }
0843:
0844:                WorkflowTO workflow = (WorkflowTO) execute(new JbpmCallback() {
0845:
0846:                    public Object doInJbpm(JbpmContext context) {
0847:
0848:                        ProcessDefinition processDefinition = null;
0849:                        try {
0850:                            InputStream is = new ByteArrayInputStream(
0851:                                    i_workflowContent);
0852:
0853:                            processDefinition = deployProcessDef(context, is,
0854:                                    comment);
0855:                        } catch (IOException ioEx) {
0856:                            logger.info("Cannot Deploy Process", ioEx);
0857:                            return null;
0858:                        }
0859:
0860:                        ProcessDefTransformer transformer = new ProcessDefTransformer(
0861:                                getWikiEngine(), context);
0862:                        return transformer.transform(processDefinition);
0863:                    }
0864:                });
0865:
0866:                return workflow;
0867:            }
0868:
0869:            /**
0870:             * Returns start step for specified workflow. It is "empty" task - it's id is null since it is not created. It
0871:             * should be used for filling required variables and any other required information, getting information about
0872:             * transition, and starting new task later with passing this step back
0873:             * 
0874:             * @param name - started workflow name
0875:             * @param version - started workflow version
0876:             * @param projectName - name of project, for which workflow is created
0877:             * @return
0878:             */
0879:            @SuppressWarnings("unchecked")
0880:            public StepTO getWorkflowStartStep(final String i_name,
0881:                    final int i_version, final String i_projectName)
0882:                    throws EmForgeException {
0883:
0884:                Object result = execute(new JbpmCallback() {
0885:
0886:                    public Object doInJbpm(JbpmContext context) {
0887:
0888:                        // get workflow
0889:                        ProcessDefinition processDef = getProcessDef(context,
0890:                                i_name, i_version);
0891:
0892:                        if (processDef == null) {
0893:                            return new EmForgeException(
0894:                                    "Cano find specified workflow");
0895:                        }
0896:
0897:                        Task startTask = processDef.getProcessDefinition()
0898:                                .getTaskMgmtDefinition().getStartTask();
0899:                        TaskDefinitionTransformer transformer = new TaskDefinitionTransformer(
0900:                                projectService, userFactory, i_projectName);
0901:
0902:                        return transformer.transform(startTask);
0903:                    }
0904:                });
0905:
0906:                if (result instanceof  EmForgeException) {
0907:                    throw (EmForgeException) result;
0908:                }
0909:
0910:                return (StepTO) result;
0911:            }
0912:
0913:            /**
0914:             * Starts new task
0915:             * 
0916:             * @param startStep - information about started task like: priority, variable values, required by start task,
0917:             *            dueDate and so on
0918:             * @param transitionName - name of transition, should be used for completing start-task
0919:             * @param tempPageName - in case then description and attachments was specified for task, they were stored in
0920:             *            temporare Wiki-Page. this param contains name of this page May be empty
0921:             * @todo tempPageName should be passed n startStep (somehow), and this method should receive content for description
0922:             * @return created task
0923:             */
0924:            public TaskTO startTask(final StepTO i_startStep,
0925:                    final String i_transitionName, final String i_tempPageName)
0926:                    throws EmForgeException {
0927:
0928:                final BpmServiceImpl bpmService = this ;
0929:
0930:                // check - is used allowed to start new task
0931:                if (!canStartNewTask(i_startStep.getProjectName())) {
0932:                    throw new AccessDeniedException(
0933:                            "You are not allowed to start new task");
0934:                }
0935:
0936:                Object result = execute(new JbpmCallback() {
0937:
0938:                    public Object doInJbpm(JbpmContext context) {
0939:
0940:                        Object proc = startTaskImpl(context, i_startStep,
0941:                                i_transitionName, i_tempPageName);
0942:
0943:                        if (proc instanceof  EmForgeException) {
0944:                            return proc;
0945:                        }
0946:
0947:                        // now, convert
0948:                        ProcessTransformer transformer = new ProcessTransformer(
0949:                                bpmService, projectService, userFactory,
0950:                                getWikiEngine(), true);
0951:
0952:                        return transformer.transform(proc);
0953:                    }
0954:
0955:                });
0956:
0957:                if (result instanceof  EmForgeException) {
0958:                    throw (EmForgeException) result;
0959:                }
0960:
0961:                TaskTO createdTask = (TaskTO) result;
0962:                return createdTask;
0963:            }
0964:
0965:            /**
0966:             * Stop Specified Task
0967:             * 
0968:             * @param taskId - id of task we need to stop
0969:             * @param comment - comment specified why task is stopped (may be empty)
0970:             * @return true is task stopped, othervise false
0971:             */
0972:            public Boolean stopTask(final long i_taskId, String i_comment)
0973:                    throws EmForgeException {
0974:
0975:                TaskTO task = getTask(i_taskId);
0976:
0977:                if (!canStopTask(task)) {
0978:                    throw new AccessDeniedException(
0979:                            "You are not allowed to stop this task");
0980:                }
0981:
0982:                if (i_comment != null) {
0983:                    addComment(i_taskId, i_comment);
0984:                }
0985:
0986:                // now, stop the process
0987:                Object result = execute(new JbpmCallback() {
0988:
0989:                    public Object doInJbpm(JbpmContext context) {
0990:
0991:                        // get process instance
0992:                        ProcessInstance process = context
0993:                                .getProcessInstance(i_taskId);
0994:
0995:                        if (process == null) {
0996:                            return new EmForgeException("Cannot find task #"
0997:                                    + i_taskId);
0998:                        }
0999:
1000:                        if (process.getEnd() != null) {
1001:                            return new EmForgeException("Task #" + i_taskId
1002:                                    + " already finished");
1003:                        }
1004:
1005:                        process.end();
1006:
1007:                        // stops all blocking tasks
1008:                        // It should be done authomatically, but according to bugs:
1009:                        // http://jira.jboss.com/jira/browse/JBPM-392 and
1010:                        // http://jira.jboss.com/jira/browse/JBPM-590 it will be fixed only in
1011:                        // 3.2
1012:                        // so, until this time we should do it by our selves
1013:                        // [AKA: Mar 11, 2008] According to comments in these bugs - it is never will be fixed.
1014:                        Collection<TaskInstance> blockingTasks = getBlockingTasks(process);
1015:                        for (TaskInstance task : blockingTasks) {
1016:                            task.setEnd(new Date());
1017:                        }
1018:
1019:                        return null;
1020:                    }
1021:                });
1022:
1023:                if (result instanceof  EmForgeException) {
1024:                    throw (EmForgeException) result;
1025:                }
1026:
1027:                return true;
1028:            }
1029:
1030:            /**
1031:             * Save task
1032:             * 
1033:             * @param task - task to be saved with all required variables set
1034:             * @param comment - comment related to changes
1035:             * @return - true if saving success
1036:             * @throws EmForgeException
1037:             */
1038:            public Boolean saveTask(final TaskTO i_task, String i_comment)
1039:                    throws EmForgeException {
1040:
1041:                if (!canChangeTask(i_task)) {
1042:                    throw new AccessDeniedException(
1043:                            "You are not allowed to change this task");
1044:                }
1045:
1046:                if (i_comment != null) {
1047:                    addComment(i_task.getId(), i_comment);
1048:                }
1049:
1050:                Object result = execute(new JbpmCallback() {
1051:
1052:                    public Object doInJbpm(JbpmContext context) {
1053:
1054:                        // try to find task instance
1055:                        ProcessInstance processInstance = context
1056:                                .getProcessInstance(i_task.getId());
1057:
1058:                        if (processInstance == null) {
1059:                            return new EmForgeException("Cannot find task #"
1060:                                    + i_task.getId());
1061:                        }
1062:
1063:                        // now, fill this process instance with all passed variables
1064:                        for (VariableTO var : i_task.getVariables()) {
1065:                            if (!BpmVariable.MILESTONE.getVariable().equals(
1066:                                    var.getLabel())) {
1067:                                setVariable(processInstance, var.getLabel(),
1068:                                        var.getValue());
1069:                            } else {
1070:                                // special processing for milestone
1071:                                // @todo It is better to avoid such convertion and store milestone and project references as
1072:                                // names, not as ID
1073:                                MilestoneDO milestone = projectService
1074:                                        .getMilestone(var.getValue());
1075:                                setVariable(processInstance, var.getLabel(),
1076:                                        milestone);
1077:                            }
1078:
1079:                            // is it one of "ASSIGN_TO" variables?
1080:                            if (Role.isVariableName(var.getLabel())
1081:                                    && !BpmSystemRole.isSystemRole(var
1082:                                            .getLabel())) {
1083:                                // in this case we should set same value into swimlane instance (if it is exists)
1084:                                SwimlaneInstance si = null;
1085:                                String roleName = Role
1086:                                        .getRoleNameFromVariableName(var
1087:                                                .getLabel());
1088:                                if (roleName != null) {
1089:                                    si = processInstance.getTaskMgmtInstance()
1090:                                            .getSwimlaneInstance(roleName);
1091:                                }
1092:
1093:                                if (si != null) {
1094:                                    // here we should check - if value is empty - that means swimlane has no any assignment
1095:                                    // we should set swimlane name itself as swimlane assignment - so, later, it will be copied
1096:                                    // into taskInstance
1097:                                    if (StringUtils.isEmpty(ObjectUtils
1098:                                            .toString(var.getValue()))) {
1099:                                        si.setActorId(roleName);
1100:                                    } else {
1101:                                        si.setActorId(ObjectUtils.toString(var
1102:                                                .getValue()));
1103:                                    }
1104:                                }
1105:                            }
1106:                        }
1107:
1108:                        // save title, priority and dueDate
1109:                        setVariable(processInstance, BpmVariable.TITLE
1110:                                .getVariable(), i_task.getTitle());
1111:                        setVariable(processInstance, BpmVariable.DUEDATE
1112:                                .getVariable(), i_task.getDueDate());
1113:                        setPriority(processInstance, i_task.getPriority()
1114:                                .getValue());
1115:
1116:                        // save start variable
1117:                        context.save(processInstance);
1118:
1119:                        return null;
1120:                    }
1121:                });
1122:
1123:                if (result instanceof  EmForgeException) {
1124:                    throw (EmForgeException) result;
1125:                }
1126:
1127:                return true;
1128:            }
1129:
1130:            /**
1131:             * Assign step to new owner
1132:             * 
1133:             * @param stepId
1134:             * @param newActor
1135:             * @param comment
1136:             * @return
1137:             * @throws EmForgeException
1138:             */
1139:            public StepTO assignStep(final StepTO i_step,
1140:                    final String i_newActor, String i_comment)
1141:                    throws EmForgeException {
1142:
1143:                if (!canChangeStep(i_step)) {
1144:                    throw new AccessDeniedException(
1145:                            "You are not allowed to change this step");
1146:                }
1147:
1148:                if (i_comment != null) {
1149:                    addComment(i_step.getTaskId(), i_comment);
1150:                }
1151:
1152:                Object result = execute(new JbpmCallback() {
1153:
1154:                    public Object doInJbpm(JbpmContext context) {
1155:
1156:                        // try to find task instance
1157:                        TaskInstance taskInstance = context
1158:                                .getTaskInstance(i_step.getId());
1159:
1160:                        if (taskInstance.getSwimlaneInstance() != null) {
1161:                            String swimlaneName = taskInstance
1162:                                    .getSwimlaneInstance().getName();
1163:                            String varName = Role.getVariableName(swimlaneName);
1164:
1165:                            // set variable in step
1166:                            if (taskInstance.getVariable(varName) != null) {
1167:                                taskInstance.setVariable(varName, i_newActor);
1168:                            }
1169:
1170:                            // also set variable in process instance
1171:                            ProcessInstance processInstance = taskInstance
1172:                                    .getToken().getProcessInstance();
1173:                            setVariable(processInstance, varName, i_newActor);
1174:                        }
1175:
1176:                        i_step.setActor(i_newActor);
1177:                        // set new actor and override swimlane value
1178:                        taskInstance.setActorId(i_newActor, true);
1179:
1180:                        // save start variable
1181:                        context.save(taskInstance);
1182:
1183:                        return i_step;
1184:                    }
1185:                });
1186:
1187:                if (result instanceof  EmForgeException) {
1188:                    throw (EmForgeException) result;
1189:                }
1190:
1191:                return i_step;
1192:            }
1193:
1194:            /**
1195:             * Change Step Priority
1196:             * 
1197:             * @param step
1198:             * @param newPriority
1199:             * @param comment
1200:             * @return
1201:             * @throws EmForgeException
1202:             */
1203:            public StepTO changeStepPriority(final StepTO i_step,
1204:                    final PriorityTO i_newPriority, String i_comment)
1205:                    throws EmForgeException {
1206:
1207:                if (!canChangeStep(i_step)) {
1208:                    throw new AccessDeniedException(
1209:                            "You are not allowed to change this step");
1210:                }
1211:
1212:                if (i_comment != null) {
1213:                    addComment(i_step.getTaskId(), i_comment);
1214:                }
1215:
1216:                i_step.setPriority(i_newPriority);
1217:
1218:                Object result = execute(new JbpmCallback() {
1219:
1220:                    public Object doInJbpm(JbpmContext context) {
1221:
1222:                        // try to find task instance
1223:                        TaskInstance taskInstance = context
1224:                                .getTaskInstance(i_step.getId());
1225:
1226:                        // change priority
1227:                        taskInstance.setPriority(i_step.getPriority()
1228:                                .getValue());
1229:
1230:                        // save start variable
1231:                        context.save(taskInstance);
1232:                        return i_step;
1233:                    }
1234:                });
1235:
1236:                if (result instanceof  EmForgeException) {
1237:                    throw (EmForgeException) result;
1238:                }
1239:
1240:                return i_step;
1241:            }
1242:
1243:            /**
1244:             * Complete step
1245:             * 
1246:             * @param step - step to be completed with all required variables set
1247:             * @param transitionName - transaction name, should be used for completion
1248:             * @param comment - comment related to completion
1249:             * @return - new state of Task processed
1250:             * @throws EmForgeException
1251:             */
1252:            public TaskTO completeStep(final StepTO i_step,
1253:                    final String i_transitionName, final String i_comment)
1254:                    throws EmForgeException {
1255:
1256:                if (!canCompleteStep(i_step)) {
1257:                    throw new AccessDeniedException(
1258:                            "You are not allowed to complete this task");
1259:                }
1260:
1261:                final BpmServiceImpl bpmService = this ;
1262:
1263:                if (i_comment != null) {
1264:                    addComment(i_step.getTaskId(), i_comment);
1265:                }
1266:
1267:                Object result = execute(new JbpmCallback() {
1268:
1269:                    public Object doInJbpm(JbpmContext context) {
1270:
1271:                        // try to find task instance
1272:                        TaskInstance taskInstance = context
1273:                                .getTaskInstance(i_step.getId());
1274:
1275:                        if (taskInstance == null) {
1276:                            return new EmForgeException("Cannot find step #"
1277:                                    + i_step.getId());
1278:                        }
1279:
1280:                        ProjectDO project = ProcessTransformer
1281:                                .getProject(taskInstance.getToken()
1282:                                        .getProcessInstance());
1283:
1284:                        // check input variables
1285:                        String message = checkVariables(i_step, taskInstance
1286:                                .getTask(), project.getName());
1287:                        if (message != null) {
1288:                            return new EmForgeException(message);
1289:                        }
1290:
1291:                        // now, fill this task instance with all passed variables
1292:                        setVariables(context, taskInstance, i_step);
1293:
1294:                        try {
1295:                            // save start variable
1296:                            context.save(taskInstance);
1297:
1298:                            // now, we need complete start task with specified transition
1299:                            closeTask(context, taskInstance, i_transitionName);
1300:                        } catch (Exception ex) {
1301:                            return new EmForgeException("Cannot complete step",
1302:                                    ex);
1303:                        }
1304:
1305:                        // now, we need to convert our process instance into task TO and return it
1306:                        // first of all - flush session and refresh object
1307:                        context.getSession().flush();
1308:                        context.getSession().refresh(
1309:                                taskInstance.getToken().getProcessInstance());
1310:
1311:                        // now, convert
1312:                        ProcessTransformer transformer = new ProcessTransformer(
1313:                                bpmService, projectService, userFactory,
1314:                                getWikiEngine(), true);
1315:
1316:                        return transformer.transform(taskInstance.getToken()
1317:                                .getProcessInstance());
1318:                    }
1319:                });
1320:
1321:                if (result instanceof  EmForgeException) {
1322:                    throw (EmForgeException) result;
1323:                }
1324:
1325:                return (TaskTO) result;
1326:            }
1327:
1328:            /**
1329:             * Returns list of currently active subtasks for specified task
1330:             * 
1331:             * @param taskId - parent task id
1332:             * @return list of active sub-tasks
1333:             */
1334:            public TaskTO[] getBlockingSubTasks(final long taskId)
1335:                    throws EmForgeException {
1336:
1337:                if (!canReadTask(taskId)) {
1338:                    throw new AccessDeniedException(
1339:                            "You are not allowed to read this task");
1340:                }
1341:
1342:                final BpmServiceImpl bpmService = this ;
1343:
1344:                Object result = execute(new JbpmCallback() {
1345:
1346:                    @SuppressWarnings("unchecked")
1347:                    public Object doInJbpm(JbpmContext context) {
1348:
1349:                        // try to find process instance
1350:                        ProcessInstance processInstance = context
1351:                                .getProcessInstance(taskId);
1352:
1353:                        if (processInstance == null) {
1354:                            return new EmForgeException("Cannot find task #"
1355:                                    + taskId);
1356:                        }
1357:
1358:                        List<ProcessInstance> blockingProcesses = getBlockingSubProcesses(
1359:                                context, processInstance);
1360:
1361:                        // now transform to collection of TaskTO
1362:                        ProcessTransformer transformer = new ProcessTransformer(
1363:                                bpmService, projectService, userFactory,
1364:                                getWikiEngine(), false);
1365:                        List<TaskTO> blockingTasks = new LinkedList<TaskTO>();
1366:                        CollectionUtils.collect(blockingProcesses, transformer,
1367:                                blockingTasks);
1368:
1369:                        return blockingTasks.toArray(new TaskTO[blockingTasks
1370:                                .size()]);
1371:                    }
1372:                });
1373:
1374:                if (result instanceof  EmForgeException) {
1375:                    throw (EmForgeException) result;
1376:                }
1377:
1378:                return (TaskTO[]) result;
1379:            }
1380:
1381:            /**
1382:             * Returns list of finished subtasks for specified task
1383:             * 
1384:             * @param taskId - parent task id
1385:             * @return list of finished sub-tasks
1386:             */
1387:            public TaskTO[] getFinishedSubTasks(final long taskId)
1388:                    throws EmForgeException {
1389:
1390:                if (!canReadTask(taskId)) {
1391:                    throw new AccessDeniedException(
1392:                            "You are not allowed to read this task");
1393:                }
1394:
1395:                final BpmServiceImpl bpmService = this ;
1396:
1397:                Object result = execute(new JbpmCallback() {
1398:
1399:                    @SuppressWarnings("unchecked")
1400:                    public Object doInJbpm(JbpmContext context) {
1401:
1402:                        // try to find process instance
1403:                        ProcessInstance processInstance = context
1404:                                .getProcessInstance(taskId);
1405:
1406:                        if (processInstance == null) {
1407:                            return new EmForgeException("Cannot find task #"
1408:                                    + taskId);
1409:                        }
1410:
1411:                        List<ProcessInstance> finishedProcesses = new LinkedList<ProcessInstance>();
1412:
1413:                        Token rootToken = processInstance.getRootToken();
1414:
1415:                        getFinishedSubProcessesFromToken(context, rootToken,
1416:                                finishedProcesses);
1417:
1418:                        // additionally get subprocesses from TasSubProcesses table
1419:                        Session session = context.getSession();
1420:                        assert session != null;
1421:
1422:                        Query query = session
1423:                                .getNamedQuery("JbpmProcessImpl.findFinishedSubProcesses");
1424:                        assert query != null;
1425:
1426:                        query.setLong("processId", processInstance.getId());
1427:                        List<ProcessInstance> subProcesses = query.list();
1428:
1429:                        // merge both
1430:                        finishedProcesses.addAll(subProcesses);
1431:
1432:                        // now transform to collection of TaskTO
1433:                        ProcessTransformer transformer = new ProcessTransformer(
1434:                                bpmService, projectService, userFactory,
1435:                                getWikiEngine(), false);
1436:                        List<TaskTO> finishedTasks = new LinkedList<TaskTO>();
1437:                        CollectionUtils.collect(finishedProcesses, transformer,
1438:                                finishedTasks);
1439:
1440:                        return finishedTasks.toArray(new TaskTO[finishedTasks
1441:                                .size()]);
1442:                    }
1443:                });
1444:
1445:                if (result instanceof  EmForgeException) {
1446:                    throw (EmForgeException) result;
1447:                }
1448:
1449:                return (TaskTO[]) result;
1450:            }
1451:
1452:            /**
1453:             * Create subtask for specified step
1454:             * 
1455:             * @param stepId - step used as parent for subtask
1456:             * @param name - name of workflow used for starting task
1457:             * @param version - version of workflow, used to start
1458:             * @return
1459:             * @throws EmForgeException
1460:             */
1461:            public TaskTO startSubTask(final long i_parentStepId,
1462:                    final StepTO i_startStep, final String i_transitionName,
1463:                    final String i_tempPageName) throws EmForgeException {
1464:
1465:                if (!canStartNewTask(i_startStep.getProjectName())) {
1466:                    throw new AccessDeniedException(
1467:                            "You are not allowed to start new task");
1468:                }
1469:
1470:                final BpmServiceImpl bpmService = this ;
1471:
1472:                Object result = execute(new JbpmCallback() {
1473:
1474:                    public Object doInJbpm(JbpmContext context) {
1475:
1476:                        // get the task instance
1477:                        TaskInstance taskInstance = context
1478:                                .getTaskInstance(i_parentStepId);
1479:                        if (taskInstance == null) {
1480:                            return new EmForgeException("Cannot find step #"
1481:                                    + i_parentStepId);
1482:                        }
1483:
1484:                        Object obj = startTaskImpl(context, i_startStep,
1485:                                i_transitionName, i_tempPageName);
1486:
1487:                        if (obj instanceof  EmForgeException) {
1488:                            return obj;
1489:                        }
1490:
1491:                        ProcessInstance subProc = (ProcessInstance) obj;
1492:
1493:                        TaskSubProcess taskSubProcess = new TaskSubProcess(
1494:                                taskInstance, subProc);
1495:                        // save it
1496:                        context.getSession().saveOrUpdate(taskSubProcess);
1497:
1498:                        // now, convert
1499:                        ProcessTransformer transformer = new ProcessTransformer(
1500:                                bpmService, projectService, userFactory,
1501:                                getWikiEngine(), true);
1502:
1503:                        return transformer.transform(subProc);
1504:                    }
1505:                });
1506:
1507:                if (result instanceof  EmForgeException) {
1508:                    throw (EmForgeException) result;
1509:                }
1510:
1511:                return (TaskTO) result;
1512:            }
1513:
1514:            /**
1515:             * Get task history
1516:             * 
1517:             * @param taskId - task id to get history
1518:             * @return
1519:             * @throws EmForgeException
1520:             */
1521:            public HistoryTO[] getTaskHistory(final long taskId)
1522:                    throws EmForgeException {
1523:
1524:                if (!canReadTask(taskId)) {
1525:                    throw new AccessDeniedException(
1526:                            "You are not allowed to read this task");
1527:                }
1528:
1529:                Object result = execute(new JbpmCallback() {
1530:
1531:                    @SuppressWarnings("unchecked")
1532:                    public Object doInJbpm(JbpmContext context) {
1533:
1534:                        // get process instance
1535:                        ProcessInstance process = context
1536:                                .getProcessInstance(taskId);
1537:
1538:                        if (process == null) {
1539:                            return new EmForgeException("Cannot find task #"
1540:                                    + taskId);
1541:                        }
1542:
1543:                        LoggingSession logSession = context.getLoggingSession();
1544:                        // TODO currently we getting logs only by ROOT token.
1545:                        // later we will need implement for child tokens too
1546:                        Collection<ProcessLog> logs = logSession
1547:                                .findLogsByToken(process.getRootToken().getId());
1548:                        List<HistoryTO> history = new LinkedList<HistoryTO>();
1549:                        ProcessLogTransformer transformer = new ProcessLogTransformer(
1550:                                emForgeContext, taskId);
1551:
1552:                        for (ProcessLog processLog : logs) {
1553:                            if (processLog
1554:                                    .getClass()
1555:                                    .equals(
1556:                                            org.jbpm.graph.log.ProcessInstanceCreateLog.class)
1557:                                    || processLog
1558:                                            .getClass()
1559:                                            .equals(
1560:                                                    org.jbpm.graph.log.ProcessInstanceEndLog.class)
1561:                                    || processLog
1562:                                            .getClass()
1563:                                            .equals(
1564:                                                    org.jbpm.taskmgmt.log.TaskEndLog.class)) {
1565:                                history.add(transformer.transform(processLog));
1566:                            }
1567:                        }
1568:
1569:                        return history.toArray(new HistoryTO[history.size()]);
1570:                    }
1571:                });
1572:
1573:                if (result instanceof  EmForgeException) {
1574:                    throw (EmForgeException) result;
1575:                }
1576:
1577:                return (HistoryTO[]) result;
1578:            }
1579:
1580:            /**
1581:             * Is it possible for currently logged user request a status for specified step
1582:             * 
1583:             * @param stepId - step id to check
1584:             * @return true if it is possible to request status
1585:             * @throws EmForgeException
1586:             */
1587:            public Boolean isPossibleRequestStatus(final long stepId)
1588:                    throws EmForgeException {
1589:
1590:                // anonymous cannot request status
1591:                if (userFactory.getCurrentUser().isAnonymous()) {
1592:                    return false;
1593:                }
1594:
1595:                Object result = execute(new JbpmCallback() {
1596:
1597:                    @SuppressWarnings("unchecked")
1598:                    public Object doInJbpm(JbpmContext context) {
1599:
1600:                        // try to get task instance
1601:                        TaskInstance taskInstance = context
1602:                                .getTaskInstance(stepId);
1603:                        if (taskInstance == null) {
1604:                            return new EmForgeException("Cannot find step #"
1605:                                    + stepId);
1606:                        }
1607:
1608:                        // is owner of step - same user as currently logged?
1609:                        if (userFactory.getCurrentUser().getUsername().equals(
1610:                                taskInstance.getActorId())) {
1611:                            return false;
1612:                        }
1613:
1614:                        String email = getTaskOwnerEmail(taskInstance);
1615:                        if (email == null) {
1616:                            // there is no email to send request
1617:                            return false;
1618:                        }
1619:
1620:                        return true;
1621:                    }
1622:                });
1623:
1624:                if (result instanceof  EmForgeException) {
1625:                    throw (EmForgeException) result;
1626:                }
1627:
1628:                return (Boolean) result;
1629:            }
1630:
1631:            /**
1632:             * Request status for specified step
1633:             * 
1634:             * @param stepId - step to request
1635:             * @param request - request message
1636:             * @return
1637:             * @throws EmForgeException
1638:             */
1639:            public Boolean requestStatus(final long stepId, final String request)
1640:                    throws EmForgeException {
1641:
1642:                if (!isPossibleRequestStatus(stepId)) {
1643:                    return false;
1644:                }
1645:
1646:                Object result = execute(new JbpmCallback() {
1647:
1648:                    @SuppressWarnings("unchecked")
1649:                    public Object doInJbpm(JbpmContext context) {
1650:
1651:                        // try to get task instance
1652:                        TaskInstance taskInstance = context
1653:                                .getTaskInstance(stepId);
1654:                        if (taskInstance == null) {
1655:                            return new EmForgeException("Cannot find step #"
1656:                                    + stepId);
1657:                        }
1658:                        // convert it into StepTO
1659:                        TaskTransformer taskTransformer = new TaskTransformer(
1660:                                projectService, userFactory);
1661:                        StepTO step = taskTransformer.transform(taskInstance);
1662:
1663:                        EmForgeUserDetails fromUser = userFactory
1664:                                .getCurrentUser();
1665:                        String toEmail = getTaskOwnerEmail(taskInstance);
1666:
1667:                        logger.info("Send status request email from "
1668:                                + fromUser.getUsername() + " to " + toEmail);
1669:
1670:                        // create task bean
1671:                        TaskStatusRequestEmail message = (TaskStatusRequestEmail) emailServices
1672:                                .getEmailFactory().createEmail(
1673:                                        "taskstatusrequest");
1674:
1675:                        message.setTask(step);
1676:                        message.setMessage(request);
1677:
1678:                        // Set up the email
1679:                        message.setPriority(EmailSender.PRIORITY_NORMAL);
1680:
1681:                        message.setSubject("Status Request For Task : \""
1682:                                + step.getTitle() + "\"");
1683:
1684:                        message.setToName(toEmail);
1685:                        message.setFromName(fromUser.getEmail());
1686:
1687:                        // send message
1688:                        try {
1689:                            emailServices.getEmailSender().sendMessage(message);
1690:
1691:                            return true;
1692:                        } catch (EmailerException ex) {
1693:                            // process error:
1694:                            // print error message
1695:                            logger.error(
1696:                                    "Cannot send task status request to email "
1697:                                            + toEmail, ex);
1698:
1699:                            return false;
1700:                        }
1701:                    }
1702:                });
1703:
1704:                if (result instanceof  EmForgeException) {
1705:                    throw (EmForgeException) result;
1706:                }
1707:
1708:                return (Boolean) result;
1709:            }
1710:
1711:            /**
1712:             * Find tasks We will have reporting service, allowed us to generate reports for any criteria. But - we will need
1713:             * also some easy-reporting - there we will able find and display list of tasks This is initial version of method,
1714:             * implemented this 'easy-reporting' it's interface will be changed in future to support more options for search
1715:             * 
1716:             * @param milestoneName -
1717:             * @param status
1718:             * @param includeSubTasks
1719:             * @return
1720:             */
1721:            @SuppressWarnings("unchecked")
1722:            public List<TaskTO> findTasks(String i_milestoneName,
1723:                    final TaskStatus i_status, final boolean i_includeSubTasks)
1724:                    throws EmForgeException {
1725:
1726:                final MilestoneDO milestone = i_milestoneName == null ? null
1727:                        : projectService.getMilestone(i_milestoneName);
1728:                final BpmServiceImpl bpmService = this ;
1729:
1730:                if (milestone == null) {
1731:                    throw new EmForgeException(
1732:                            "Only search by milestones supported for now");
1733:                }
1734:
1735:                Object result = execute(new JbpmCallback() {
1736:
1737:                    @SuppressWarnings("unchecked")
1738:                    public Object doInJbpm(JbpmContext context) {
1739:
1740:                        Session dbSession = context.getSession();
1741:                        Query query = null;
1742:
1743:                        if (i_status == TaskStatus.OPENED) {
1744:                            if (i_includeSubTasks) {
1745:                                query = dbSession
1746:                                        .getNamedQuery("Milestone.findOpenedProcesses");
1747:                            } else {
1748:                                query = dbSession
1749:                                        .getNamedQuery("Milestone.findOpenedProcessesExceptSubprocesses");
1750:                            }
1751:                        } else {
1752:                            if (i_includeSubTasks) {
1753:                                query = dbSession
1754:                                        .getNamedQuery("Milestone.findClosedProcesses");
1755:                            } else {
1756:                                query = dbSession
1757:                                        .getNamedQuery("Milestone.findClosedProcessesExceptSubprocesses");
1758:                            }
1759:                        }
1760:
1761:                        query.setLong("milestoneId", milestone.getId());
1762:                        List<ProcessInstance> processes = query.list();
1763:
1764:                        // convert it to TO
1765:                        ProcessTransformer transformer = new ProcessTransformer(
1766:                                bpmService, projectService, userFactory,
1767:                                getWikiEngine(), false);
1768:                        List<TaskTO> tasks = new TaskCollection(processes,
1769:                                transformer);
1770:
1771:                        return tasks;
1772:                    }
1773:                });
1774:
1775:                if (result instanceof  EmForgeException) {
1776:                    throw (EmForgeException) result;
1777:                }
1778:                return (List<TaskTO>) result;
1779:            }
1780:
1781:            //
1782:            // Security Checks
1783:            //
1784:
1785:            /**
1786:             * is current user allowed to read specified task Currently anybody can see any task
1787:             * 
1788:             * @param stepId
1789:             * @return
1790:             */
1791:            public boolean canReadTask(long stepId) {
1792:
1793:                return true;
1794:            }
1795:
1796:            /**
1797:             * is current user allowed to complete specified step
1798:             * 
1799:             * @param stepId
1800:             * @return
1801:             */
1802:            public boolean canCompleteStep(StepTO step) {
1803:
1804:                if (step == null) {
1805:                    return false;
1806:                }
1807:
1808:                return isStepOwner(step) || isGroupMember(step)
1809:                        || isProjectManager(step.getProjectName()) || isAdmin();
1810:            }
1811:
1812:            /**
1813:             * Is Current User allowed to edit task description
1814:             * 
1815:             * @param taskId
1816:             * @return
1817:             */
1818:            public boolean canEditTaskDescription(TaskTO task) {
1819:
1820:                if (task == null) {
1821:                    return false;
1822:                }
1823:
1824:                return (isTaskOwner(task)
1825:                        || isProjectManager(task.getProjectName()) || isAdmin())
1826:                        && !task.getHasEnded();
1827:            }
1828:
1829:            /**
1830:             * Is Current user allowed to add attachment for task
1831:             * 
1832:             * @param taskId
1833:             * @return
1834:             */
1835:            public boolean canAddAttachment(long taskId) {
1836:
1837:                return !userFactory.getCurrentUser().isAnonymous();
1838:            }
1839:
1840:            /**
1841:             * Is current user allowed to add comment for the task
1842:             * 
1843:             * @param taskId
1844:             * @return
1845:             */
1846:            public boolean canCommentTask(long taskId) {
1847:
1848:                return !userFactory.getCurrentUser().isAnonymous();
1849:            }
1850:
1851:            /**
1852:             * Is current user allowed to close the specified task
1853:             * 
1854:             * @param taskId
1855:             * @return
1856:             */
1857:            public boolean canStopTask(TaskTO task) {
1858:
1859:                if (task == null) {
1860:                    return false;
1861:                }
1862:
1863:                return (isTaskOwner(task)
1864:                        || isProjectManager(task.getProjectName()) || isAdmin())
1865:                        && !task.getHasEnded();
1866:            }
1867:
1868:            /**
1869:             * Is current user allowed to change the task
1870:             * 
1871:             * @param taskId
1872:             * @return
1873:             */
1874:            public boolean canChangeTask(TaskTO task) {
1875:
1876:                if (task == null) {
1877:                    return false;
1878:                }
1879:
1880:                return (isTaskOwner(task)
1881:                        || isProjectManager(task.getProjectName()) || isAdmin())
1882:                        && !task.getHasEnded();
1883:            }
1884:
1885:            /**
1886:             * Is current user allowed to change the step
1887:             * 
1888:             * @param stepId
1889:             * @return
1890:             */
1891:            public boolean canChangeStep(StepTO step) {
1892:
1893:                if (step == null) {
1894:                    return false;
1895:                }
1896:
1897:                return isStepOwner(step) || isGroupMember(step)
1898:                        || isProjectManager(step.getProjectName()) || isAdmin();
1899:            }
1900:
1901:            /**
1902:             * Is Current user allowed to reassign the steps for specified task
1903:             * 
1904:             * @param stepId
1905:             * @return
1906:             */
1907:            public boolean canReassignSteps(TaskTO task) {
1908:
1909:                if (task == null) {
1910:                    return false;
1911:                }
1912:
1913:                return (isProjectManager(task.getProjectName()) || isAdmin())
1914:                        && !task.getHasEnded();
1915:            }
1916:
1917:            /**
1918:             * Is current user allowed to add new workflows
1919:             * 
1920:             * @return
1921:             */
1922:            public boolean canAddNewWorkflow() {
1923:
1924:                return isAdmin();
1925:            }
1926:
1927:            /**
1928:             * Is Current user allowed to start new tasks for specified project
1929:             * 
1930:             * @param projectName
1931:             * @return
1932:             */
1933:            public boolean canStartNewTask(String projectName) {
1934:
1935:                // currently logged-in user allowed to start task for any project
1936:                return !userFactory.getCurrentUser().isAnonymous();
1937:            }
1938:
1939:            //
1940:            // Utility Functions
1941:            //
1942:
1943:            /**
1944:             * @param i_process
1945:             * @return
1946:             */
1947:            protected TaskInstance getParentTask(final ProcessInstance i_process) {
1948:
1949:                TaskInstance task = (TaskInstance) execute(new JbpmCallback() {
1950:
1951:                    @SuppressWarnings("unchecked")
1952:                    public Object doInJbpm(JbpmContext context) {
1953:
1954:                        Query query = context.getSession().getNamedQuery(
1955:                                "JbpmProcessImpl.findSuperTask");
1956:                        query.setLong("processId", i_process.getId());
1957:
1958:                        List<TaskInstance> super Tasks = query.list();
1959:
1960:                        if (super Tasks.size() > 0) {
1961:                            // get first task
1962:                            TaskInstance super Task = super Tasks.iterator()
1963:                                    .next();
1964:                            return super Task;
1965:                        }
1966:
1967:                        return null;
1968:                    }
1969:                });
1970:
1971:                return task;
1972:            }
1973:
1974:            /**
1975:             * @param process
1976:             * @return
1977:             */
1978:            @SuppressWarnings("unchecked")
1979:            protected Date getLastProcessChangesDate(
1980:                    final ProcessInstance process) {
1981:
1982:                Map<Token, List<ProcessLog>> logMap = (Map<Token, List<ProcessLog>>) execute(new JbpmCallback() {
1983:
1984:                    public Object doInJbpm(JbpmContext context) {
1985:
1986:                        LoggingSession logSession = context.getLoggingSession();
1987:                        return logSession.findLogsByProcessInstance(process
1988:                                .getId());
1989:                    }
1990:                });
1991:
1992:                // currently get logs only for root token
1993:                // we cannot use Collection here due to reason that we need last log
1994:                List<ProcessLog> logs = (List<ProcessLog>) logMap.get(process
1995:                        .getRootToken());
1996:
1997:                if (logs.size() == 0) {
1998:                    return null;
1999:                }
2000:
2001:                ProcessLog log = (ProcessLog) logs.get(logs.size() - 1);
2002:                return log.getDate();
2003:            }
2004:
2005:            /**
2006:             * Get List of Blocking tasks for Process
2007:             */
2008:            static protected Collection<TaskInstance> getBlockingTasks(
2009:                    ProcessInstance process) {
2010:
2011:                // get the root token
2012:                Token rootToken = process.getRootToken();
2013:
2014:                LinkedList<TaskInstance> blockingTasks = new LinkedList<TaskInstance>();
2015:
2016:                getBlockingTasksFromToken(rootToken, blockingTasks);
2017:
2018:                return blockingTasks;
2019:            }
2020:
2021:            /**
2022:             * @param i_token
2023:             * @param o_blockingTasks
2024:             */
2025:            @SuppressWarnings("unchecked")
2026:            static private void getBlockingTasksFromToken(Token i_token,
2027:                    Collection<TaskInstance> o_blockingTasks) {
2028:
2029:                Map children = i_token.getChildren();
2030:                if (children != null && children.size() > 0) {
2031:                    Collection childTokens = children.values();
2032:                    for (Iterator iterator = childTokens.iterator(); iterator
2033:                            .hasNext();) {
2034:                        Token child = (Token) iterator.next();
2035:                        getBlockingTasksFromToken(child, o_blockingTasks);
2036:                    }
2037:                }
2038:
2039:                TaskMgmtInstance tmi = i_token.getProcessInstance()
2040:                        .getTaskMgmtInstance();
2041:                assert tmi != null;
2042:
2043:                Collection<TaskInstance> unfinishedTasks = tmi
2044:                        .getUnfinishedTasks(i_token);
2045:
2046:                for (TaskInstance task : unfinishedTasks) {
2047:                    o_blockingTasks.add(task);
2048:                }
2049:            }
2050:
2051:            /**
2052:             * @param process
2053:             * @return
2054:             */
2055:            @SuppressWarnings("unchecked")
2056:            protected Collection<TaskInstance> getAllBlockers(
2057:                    final ProcessInstance process) {
2058:
2059:                Collection<TaskInstance> blockers = (Collection<TaskInstance>) execute(new JbpmCallback() {
2060:
2061:                    public Object doInJbpm(JbpmContext context) {
2062:
2063:                        Collection<TaskInstance> result = getBlockingTasks(process);
2064:
2065:                        for (ProcessInstance subProcess : getBlockingSubProcesses(
2066:                                context, process)) {
2067:                            result.addAll(getBlockingTasks(subProcess));
2068:                        }
2069:
2070:                        return result;
2071:                    }
2072:                });
2073:
2074:                return blockers;
2075:            }
2076:
2077:            /**
2078:             * @param i_token
2079:             * @param o_result
2080:             */
2081:            @SuppressWarnings("unchecked")
2082:            private void addComments(Token i_token, Collection<Comment> o_result) {
2083:
2084:                // add comments from currently processed token
2085:                if (i_token.getComments() != null) {
2086:                    o_result.addAll(i_token.getComments());
2087:                }
2088:
2089:                // process all subtokens
2090:                // for fixing #3317 - seems sometimes i_token.getChildren returns null
2091:                if (i_token.getChildren() != null
2092:                        && i_token.getChildren().values() != null) {
2093:                    Iterator iter = i_token.getChildren().values().iterator();
2094:                    while (iter.hasNext()) {
2095:                        Token subToken = (Token) iter.next();
2096:                        addComments(subToken, o_result);
2097:                    }
2098:                }
2099:            }
2100:
2101:            /**
2102:             * Closed task instance with specified transition and returned next task instance, in case, then it is assigned to
2103:             * same user
2104:             * 
2105:             * @param context
2106:             * @param task
2107:             * @param i_transitionName
2108:             * @return
2109:             */
2110:            private TaskInstance closeTask(JbpmContext context,
2111:                    TaskInstance task, String i_transitionName) {
2112:
2113:                String taskActor = task.getActorId();
2114:
2115:                LoggingInstance loggingInstance = task.getContextInstance()
2116:                        .getProcessInstance().getLoggingInstance();
2117:
2118:                // Sometimes we can make several assignments during one request
2119:                // for example then we create new process - fist we create
2120:                // start task, fill it wil values
2121:                // and then close it - in this case this value will be not 0
2122:                // but 1 - or probubly more
2123:                int assignmentsBefore = loggingInstance.getLogs(
2124:                        TaskAssignLog.class).size();
2125:
2126:                // end processing task
2127:                if (StringUtils.isEmpty(i_transitionName)) {
2128:                    task.end();
2129:                } else {
2130:                    task.end(i_transitionName);
2131:                }
2132:
2133:                context.save(task);
2134:
2135:                // see how many tasks were assigned after finishing this task.
2136:                // if only one task was assigned to same user - we will
2137:                // automatically
2138:                // open task-window for this task
2139:                List<?> assignmentLogs = loggingInstance
2140:                        .getLogs(TaskAssignLog.class);
2141:
2142:                if (assignmentLogs.size() - assignmentsBefore == 1) {
2143:                    // only one new task was assigned
2144:                    TaskAssignLog assignLog = (TaskAssignLog) assignmentLogs
2145:                            .get(assignmentsBefore);
2146:                    assert assignLog != null;
2147:
2148:                    String assignedTo = assignLog.getTaskNewActorId();
2149:                    TaskInstance nextTask = assignLog.getTaskInstance();
2150:
2151:                    // and it was assigned to the same actor as current task
2152:                    if (taskActor != null && taskActor.equals(assignedTo)) {
2153:                        // return this next task
2154:                        return nextTask;
2155:                    }
2156:                }
2157:
2158:                // return null
2159:                return null;
2160:
2161:            }
2162:
2163:            /**
2164:             * Checks the variables, passed in step - is all required variables specified?
2165:             * 
2166:             * @param step - step passsed into service
2167:             * @param task - related task definition
2168:             * @return null if everything ok, othervise returns error message
2169:             */
2170:            private String checkVariables(StepTO step, Task task,
2171:                    String projectName) {
2172:
2173:                // in any case - title should not be empty!
2174:                if (StringUtils.isEmpty(step.getTitle())) {
2175:                    return "Task Title cannot be empty!";
2176:                }
2177:
2178:                List<VariableAccess> writableVariables = TaskDefinitionTransformer
2179:                        .getWritableVariables(task);
2180:
2181:                for (VariableAccess variable : writableVariables) {
2182:                    // variable requried - check what it is specified!
2183:                    VariableTO var = step.getVariable(variable.getMappedName());
2184:
2185:                    if (variable.isRequired()) {
2186:                        if (var == null || StringUtils.isEmpty(var.getValue())) {
2187:                            return "Value for variable \""
2188:                                    + variable.getMappedName()
2189:                                    + "\" should be specified";
2190:                        }
2191:                    }
2192:
2193:                    // for variables, has selectValues - check - is specified value included into them
2194:                    VariableTransformer transformer = new VariableTransformer(
2195:                            projectService, userFactory, null, projectName);
2196:
2197:                    SelectValueTO[] selectValues = transformer
2198:                            .getVarSelectValues(variable.getMappedName());
2199:
2200:                    // is select Values specified?
2201:                    if (selectValues != null && selectValues.length > 0
2202:                            && var != null) {
2203:
2204:                        // try to find assigned to var value in these selectValues
2205:                        Boolean valueFound = false;
2206:                        for (SelectValueTO selectValue : selectValues) {
2207:                            if (StringUtils.equals(var.getValue(), selectValue
2208:                                    .getValue())) {
2209:                                valueFound = true;
2210:                                break;
2211:                            }
2212:                        }
2213:
2214:                        // is found?
2215:                        if (!valueFound) {
2216:                            // no - error
2217:                            return "Incorrect value specified for variable "
2218:                                    + var.getDisplayLabel();
2219:                        }
2220:                    }
2221:                }
2222:
2223:                return null;
2224:            }
2225:
2226:            /**
2227:             * Copy Variables from Step to TaskInstance
2228:             * 
2229:             * @param i_context
2230:             * @param i_taskInstance
2231:             * @param i_step
2232:             */
2233:            private void setVariables(JbpmContext i_context,
2234:                    TaskInstance i_taskInstance, StepTO i_step) {
2235:
2236:                for (VariableTO var : i_step.getWritableVariables()) {
2237:                    if (!BpmVariable.MILESTONE.getVariable().equals(
2238:                            var.getLabel())) {
2239:                        i_taskInstance.setVariable(var.getLabel(), var
2240:                                .getValue());
2241:                    } else {
2242:                        // special processing for milestone
2243:                        // @todo It is better to avoid such convertion and store milestone and project references as names, not
2244:                        // as ID
2245:                        MilestoneDO milestone = projectService.getMilestone(var
2246:                                .getValue());
2247:                        i_taskInstance.setVariable(var.getLabel(), milestone);
2248:                    }
2249:
2250:                    // is it one of "ASSIGN_TO" variables?
2251:                    if (Role.isVariableName(var.getLabel())
2252:                            && !BpmSystemRole.isSystemRole(var.getLabel())) {
2253:                        // in this case we should set same value into swimlane instance (if it is exists)
2254:                        SwimlaneInstance si = null;
2255:                        String roleName = Role.getRoleNameFromVariableName(var
2256:                                .getLabel());
2257:                        if (roleName != null) {
2258:                            si = i_taskInstance.getTaskMgmtInstance()
2259:                                    .getSwimlaneInstance(roleName);
2260:                        }
2261:
2262:                        if (si != null) {
2263:                            // here we should check - if value is empty - that means swimlane has no any assignment
2264:                            // we should set swimlane name itself as swimlane assignment - so, later, it will be copied into
2265:                            // taskInstance
2266:                            if (StringUtils.isEmpty(ObjectUtils.toString(var
2267:                                    .getValue()))) {
2268:                                si.setActorId(roleName);
2269:                            } else {
2270:                                si.setActorId(ObjectUtils.toString(var
2271:                                        .getValue()));
2272:                            }
2273:                        }
2274:                    }
2275:                }
2276:            }
2277:
2278:            /**
2279:             * Returns list of blocking subprocess instances
2280:             * 
2281:             * @param context
2282:             * @param processInstance
2283:             * @return
2284:             */
2285:            @SuppressWarnings("unchecked")
2286:            static protected List<ProcessInstance> getBlockingSubProcesses(
2287:                    JbpmContext context, ProcessInstance processInstance) {
2288:
2289:                List<ProcessInstance> blockingProcesses = new LinkedList<ProcessInstance>();
2290:
2291:                Token rootToken = processInstance.getRootToken();
2292:
2293:                getBlockingSubProcessesFromToken(rootToken, blockingProcesses);
2294:
2295:                // additionally get subprocesses from TasSubProcesses table
2296:                Session session = context.getSession();
2297:                assert session != null;
2298:
2299:                Query query = session
2300:                        .getNamedQuery("JbpmProcessImpl.findSubProcesses");
2301:                assert query != null;
2302:
2303:                query.setLong("processId", processInstance.getId());
2304:                List<ProcessInstance> subProcesses = query.list();
2305:
2306:                // merge both
2307:                blockingProcesses.addAll(subProcesses);
2308:                return blockingProcesses;
2309:            }
2310:
2311:            /**
2312:             * Returns list of blocking subprocesses for specified token
2313:             * 
2314:             * @param i_token
2315:             * @param o_blockingSubProcesses
2316:             */
2317:            @SuppressWarnings("unchecked")
2318:            static private void getBlockingSubProcessesFromToken(Token i_token,
2319:                    Collection<ProcessInstance> o_blockingSubProcesses) {
2320:
2321:                Map<?, Token> children = i_token.getChildren();
2322:                if (children != null && children.size() > 0) {
2323:                    Collection<Token> childTokens = children.values();
2324:                    for (Token child : childTokens) {
2325:                        getBlockingSubProcessesFromToken(child,
2326:                                o_blockingSubProcesses);
2327:                    }
2328:                }
2329:
2330:                ProcessInstance subProcess = i_token.getSubProcessInstance();
2331:                if (subProcess != null) {
2332:                    o_blockingSubProcesses.add(subProcess);
2333:                }
2334:            }
2335:
2336:            /**
2337:             * Returns list of finished subprocesses for specified token
2338:             * 
2339:             * @param i_token
2340:             * @param o_finishedSubProcesses
2341:             */
2342:            @SuppressWarnings("unchecked")
2343:            private void getFinishedSubProcessesFromToken(JbpmContext context,
2344:                    Token i_token,
2345:                    Collection<ProcessInstance> o_finishedSubProcesses) {
2346:
2347:                Map<?, Token> children = i_token.getChildren();
2348:                if (children != null && children.size() > 0) {
2349:                    Collection<Token> childTokens = children.values();
2350:                    for (Token child : childTokens) {
2351:                        getBlockingSubProcessesFromToken(child,
2352:                                o_finishedSubProcesses);
2353:                    }
2354:                }
2355:
2356:                // @todo
2357:                // it seems we should get this information from history
2358:                // but in my test I did not found any ProcessState log entry
2359:                // need to investigate more
2360:                LoggingSession logSession = context.getLoggingSession();
2361:                List<ProcessLog> logs = logSession.findLogsByToken(i_token
2362:                        .getId());
2363:
2364:                for (ProcessLog log : logs) {
2365:                    if (log instanceof  ProcessStateLog) {
2366:                        logger.debug("log:" + log);
2367:                    }
2368:                }
2369:            }
2370:
2371:            /**
2372:             * Gets process definition by name and version
2373:             * 
2374:             * @param i_context
2375:             * @param i_name
2376:             * @param i_version
2377:             * @return
2378:             */
2379:            private ProcessDefinition getProcessDef(JbpmContext i_context,
2380:                    String i_name, int i_version) {
2381:
2382:                ProcessDefinition processDef = null;
2383:
2384:                if (i_version == WORKFLOW_LAST_VERSION) {
2385:                    processDef = i_context.getGraphSession()
2386:                            .findLatestProcessDefinition(i_name);
2387:                } else {
2388:                    processDef = i_context.getGraphSession()
2389:                            .findProcessDefinition(i_name, i_version);
2390:                }
2391:
2392:                return processDef;
2393:            }
2394:
2395:            /**
2396:             * Returns Process Definition by id
2397:             * 
2398:             * @param i_context
2399:             * @param processDefId
2400:             * @return
2401:             */
2402:            private ProcessDefinition getProcessDef(JbpmContext i_context,
2403:                    long processDefId) {
2404:
2405:                ProcessDefinition processDef = null;
2406:
2407:                processDef = i_context.getGraphSession().getProcessDefinition(
2408:                        processDefId);
2409:
2410:                return processDef;
2411:            }
2412:
2413:            /**
2414:             * Gets email of owner of task Owner may be user or role
2415:             * 
2416:             * @param i_task
2417:             * @return
2418:             */
2419:            private String getTaskOwnerEmail(TaskInstance i_task) {
2420:
2421:                EmForgeUserDetails toUser = null;
2422:
2423:                try {
2424:                    toUser = userFactory.getUser(i_task.getActorId());
2425:                } catch (Exception ex) {
2426:                    // just ignore it here
2427:                }
2428:
2429:                if (toUser != null) {
2430:                    return toUser.getEmail();
2431:                } else {
2432:                    // probably it is a group?
2433:                    ProjectDO project = ProcessTransformer.getProject(i_task
2434:                            .getToken().getProcessInstance());
2435:                    ProjectRole projectRole = userDao
2436:                            .getEmailByRoleNameAndProjectId(
2437:                                    i_task.getActorId(), project.getId());
2438:
2439:                    if (projectRole != null) {
2440:                        return projectRole.getEmail();
2441:                    } else {
2442:                        return null;
2443:                    }
2444:                }
2445:            }
2446:
2447:            /**
2448:             * Set Variable into process instance
2449:             * 
2450:             * @param processInstance
2451:             * @param label
2452:             * @param value
2453:             */
2454:            static private void setVariable(ProcessInstance processInstance,
2455:                    String label, Object value) {
2456:
2457:                ContextInstance context = processInstance.getContextInstance();
2458:                context.setVariable(label, value);
2459:            }
2460:
2461:            /**
2462:             * @param processInstance
2463:             * @param dueDate
2464:             */
2465:            public static void setDueDate(ProcessInstance processInstance,
2466:                    Date dueDate) {
2467:
2468:                setVariable(processInstance, BpmVariable.DUEDATE.getVariable(),
2469:                        dueDate);
2470:            }
2471:
2472:            /**
2473:             * @param processInstance
2474:             * @param project
2475:             */
2476:            public static void setProject(ProcessInstance processInstance,
2477:                    ProjectDO project) {
2478:
2479:                setVariable(processInstance, BpmVariable.PROJECT.getVariable(),
2480:                        project);
2481:            }
2482:
2483:            /**
2484:             * Set Priority into Process Instance
2485:             * 
2486:             * @param i_priority
2487:             */
2488:            public static void setPriority(ProcessInstance processInstance,
2489:                    Integer i_priority) {
2490:
2491:                ContextInstance context = processInstance.getContextInstance();
2492:                assert context != null;
2493:
2494:                // get current priority
2495:                Integer currentPrio = null;
2496:                if (context.hasVariable(BpmVariable.PRIORITY.getVariable())
2497:                        && context.getVariable(BpmVariable.PRIORITY
2498:                                .getVariable()) != null) {
2499:                    Integer priority = Integer.valueOf(context.getVariable(
2500:                            BpmVariable.PRIORITY.getVariable()).toString());
2501:                    assert priority != null;
2502:
2503:                    currentPrio = priority;
2504:                }
2505:
2506:                // if currentPrio is not same as new prio
2507:                if (currentPrio == null || !currentPrio.equals(i_priority)) {
2508:                    // set new value to the variable
2509:                    context.setVariable(BpmVariable.PRIORITY.getVariable(),
2510:                            i_priority);
2511:
2512:                    // propagate this priority to the all active tasks
2513:                    Collection<TaskInstance> unfinishedTasks = getBlockingTasks(processInstance);
2514:                    assert unfinishedTasks != null;
2515:
2516:                    for (TaskInstance task : unfinishedTasks) {
2517:                        task.setPriority(i_priority);
2518:                    }
2519:
2520:                    // and subprocesses
2521:                    List<ProcessInstance> blockingProcesses = new LinkedList<ProcessInstance>();
2522:                    Token rootToken = processInstance.getRootToken();
2523:                    getBlockingSubProcessesFromToken(rootToken,
2524:                            blockingProcesses);
2525:
2526:                    for (ProcessInstance subProcess : blockingProcesses) {
2527:                        setPriority(subProcess, i_priority);
2528:                    }
2529:                }
2530:            }
2531:
2532:            /**
2533:             * @param i_context
2534:             * @param i_startStep
2535:             * @param i_transitionName
2536:             * @param i_tempPageName
2537:             * @return
2538:             */
2539:            private Object startTaskImpl(JbpmContext i_context,
2540:                    StepTO i_startStep, String i_transitionName,
2541:                    String i_tempPageName) {
2542:
2543:                // get workflow
2544:                ProcessDefinition processDef = null;
2545:                if (i_startStep.getWorkflowVersion() == null
2546:                        || i_startStep.getWorkflowVersion().equals(
2547:                                WORKFLOW_LAST_VERSION)) {
2548:                    processDef = i_context.getGraphSession()
2549:                            .findLatestProcessDefinition(
2550:                                    i_startStep.getWorkflowName());
2551:                } else {
2552:                    processDef = i_context.getGraphSession()
2553:                            .findProcessDefinition(
2554:                                    i_startStep.getWorkflowName(),
2555:                                    i_startStep.getWorkflowVersion());
2556:                }
2557:
2558:                if (processDef == null) {
2559:                    return new EmForgeException(
2560:                            "Cannot find specified workflow");
2561:                }
2562:
2563:                // create new process instance
2564:                ProcessInstance proc = new ProcessInstance(processDef);
2565:                assert proc != null;
2566:
2567:                // get project
2568:                ProjectDO project = projectService.getProject(i_startStep
2569:                        .getProjectName());
2570:
2571:                // create a new taskinstance for the start task
2572:                TaskInstance task = proc.getTaskMgmtInstance()
2573:                        .createStartTaskInstance();
2574:                assert task != null;
2575:
2576:                // check variables
2577:                String message = checkVariables(i_startStep, task.getTask(),
2578:                        project.getName());
2579:                if (message != null) {
2580:                    return new EmForgeException(message);
2581:                }
2582:
2583:                // set owner
2584:                task.setVariable(BpmVariable.OWNER.getVariable(), userFactory
2585:                        .getCurrentUser().getUsername());
2586:                // set project
2587:                task.setVariable(BpmVariable.PROJECT.getVariable(), project);
2588:
2589:                // initialize other default fields
2590:                task.setVariable(BpmVariable.TITLE.getVariable(), i_startStep
2591:                        .getTitle());
2592:                task.setPriority(i_startStep.getPriority().getValue());
2593:                setPriority(proc, i_startStep.getPriority().getValue());
2594:                task.setVariable(BpmVariable.DUEDATE.getVariable(), i_startStep
2595:                        .getDueDate());
2596:
2597:                // now, fill this task instance with all passed variables
2598:                for (VariableTO var : i_startStep.getWritableVariables()) {
2599:                    if (!BpmVariable.MILESTONE.getVariable().equals(
2600:                            var.getLabel())) {
2601:                        task.setVariable(var.getLabel(), var.getValue());
2602:                    } else {
2603:                        // special processing for milestone
2604:                        // @todo It is better to avoid such convertion and store milestone and project references as names, not
2605:                        // as ID
2606:                        MilestoneDO milestone = projectService.getMilestone(var
2607:                                .getValue());
2608:                        task.setVariable(var.getLabel(), milestone);
2609:                    }
2610:
2611:                }
2612:
2613:                // save start variable
2614:                i_context.save(task);
2615:
2616:                // now, we need complete start task with specified transition
2617:                closeTask(i_context, task, i_transitionName);
2618:
2619:                // if temporary wiki page was specified - we should rename it into process id
2620:                // so, it's contents will be available as task description
2621:                if (!StringUtils.isEmpty(i_tempPageName)) {
2622:                    WikiPage newpage = new WikiPage(getWikiEngine(),
2623:                            i_tempPageName);
2624:                    WikiContext wikiContext = new WikiContext(getWikiEngine(),
2625:                            newpage);
2626:
2627:                    try {
2628:                        getWikiEngine().renamePage(wikiContext, i_tempPageName,
2629:                                String.valueOf(proc.getId()), false);
2630:                    } catch (WikiException wikiException) {
2631:                        logger.error("Cannot rename teporary page "
2632:                                + i_tempPageName + " into task page "
2633:                                + String.valueOf(proc.getId()), wikiException);
2634:                    }
2635:                }
2636:
2637:                // now, we need to convert our process instance into task TO and return it
2638:                // first of all - flush session and refresh object
2639:                i_context.getSession().flush();
2640:                i_context.getSession().refresh(proc);
2641:
2642:                return proc;
2643:            }
2644:
2645:            /**
2646:             * Is current user owner of specified task?
2647:             * 
2648:             * @param i_task
2649:             * @return
2650:             */
2651:            private boolean isTaskOwner(TaskTO i_task) {
2652:
2653:                return userFactory.getCurrentUser().getUsername().equals(
2654:                        i_task.getOwner());
2655:            }
2656:
2657:            /**
2658:             * Is current user project manager for project, related to specified task?
2659:             * 
2660:             * @param i_task
2661:             * @return
2662:             */
2663:            private boolean isProjectManager(String projectName) {
2664:
2665:                ProjectDO project = projectService.getProject(projectName);
2666:                if (project != null) {
2667:                    return projectService.hasRole(project, userFactory
2668:                            .getCurrentUser(), ProjectService.ROLE_MANAGER);
2669:
2670:                }
2671:
2672:                return false;
2673:
2674:            }
2675:
2676:            /**
2677:             * Is Current user - Site Admin?
2678:             * 
2679:             * @return
2680:             */
2681:            private boolean isAdmin() {
2682:
2683:                return userFactory.getCurrentUser().hasRole(
2684:                        SiteRole.ADMIN.getId());
2685:            }
2686:
2687:            /**
2688:             * @param i_step
2689:             * @return
2690:             */
2691:            private boolean isStepOwner(StepTO i_step) {
2692:
2693:                return StringUtils.equals(userFactory.getCurrentUser()
2694:                        .getUsername(), i_step.getActor());
2695:            }
2696:
2697:            /**
2698:             * @param i_step
2699:             * @return
2700:             */
2701:            private boolean isGroupMember(StepTO i_step) {
2702:
2703:                ProjectDO project = projectService.getProject(i_step
2704:                        .getProjectName());
2705:                if (project == null) {
2706:                    return false;
2707:                }
2708:
2709:                // Is task owner - role name?
2710:                Role role = getAssignedRole(i_step);
2711:                if (role == null) {
2712:                    return false;
2713:                }
2714:
2715:                return projectService.hasRole(project, userFactory
2716:                        .getCurrentUser(), role);
2717:            }
2718:
2719:            /**
2720:             * @param i_step
2721:             * @return
2722:             */
2723:            private Role getAssignedRole(StepTO i_step) {
2724:
2725:                // Is task owner - role name?
2726:                Role role = userFactory.getRole(i_step.getActor());
2727:                return role;
2728:            }
2729:
2730:            /**
2731:             * @param i_context
2732:             * @param i_is
2733:             * @param i_comment
2734:             * @return
2735:             * @throws IOException
2736:             */
2737:            private ProcessDefinition deployProcessDef(JbpmContext i_context,
2738:                    InputStream i_is, String i_comment) throws IOException {
2739:
2740:                ZipInputStream zis = new ZipInputStream(i_is);
2741:                ProcessDefinition processDefinition = ProcessDefinition
2742:                        .parseParZipInputStream(zis);
2743:
2744:                // add special events
2745:                logger.info("Adding special events handlers: "
2746:                        + processDefinition.getName());
2747:
2748:                // add event for processing task-create action
2749:                Action taskCreateAction = new Action();
2750:                taskCreateAction.setActionDelegation(EmForgeJpdlReader
2751:                        .createSpringDelegation("taskCreatedEvent"));
2752:
2753:                Event taskCreateEvent = new Event(Event.EVENTTYPE_TASK_CREATE);
2754:                taskCreateEvent.addAction(taskCreateAction);
2755:
2756:                processDefinition.addEvent(taskCreateEvent);
2757:                // -----
2758:
2759:                // add event for processing task-assign action
2760:                Action taskAssignAction = new Action();
2761:                taskAssignAction.setActionDelegation(EmForgeJpdlReader
2762:                        .createSpringDelegation("taskAssignEvent"));
2763:
2764:                Event taskAssignEvent = new Event(Event.EVENTTYPE_TASK_ASSIGN);
2765:                taskAssignEvent.addAction(taskAssignAction);
2766:
2767:                processDefinition.addEvent(taskAssignEvent);
2768:                // -----
2769:
2770:                // add event for creation subprocess and propagation process data from superprocess to subprocess
2771:                Action subProcessCreateAction = new Action();
2772:                subProcessCreateAction.setActionDelegation(EmForgeJpdlReader
2773:                        .createSpringDelegation("subprocessCreatedEvent"));
2774:
2775:                Event subProcessCreateEvent = new Event(
2776:                        Event.EVENTTYPE_SUBPROCESS_CREATED);
2777:                subProcessCreateEvent.addAction(subProcessCreateAction);
2778:
2779:                processDefinition.addEvent(subProcessCreateEvent);
2780:                // -----
2781:
2782:                String userName = "";
2783:                if (userFactory.getCurrentUser() != null) {
2784:                    userName = userFactory.getCurrentUser().getUsername();
2785:                }
2786:
2787:                // create comment by adding date and user information
2788:                String fullComment = DATE_SEPARATOR + (new Date()).getTime()
2789:                        + USER_SEPARATOR + userName + MESSAGE_SEPARATOR
2790:                        + i_comment;
2791:                processDefinition.getFileDefinition().addFile(COMMENT_FILENAME,
2792:                        fullComment.getBytes());
2793:
2794:                logger
2795:                        .info("Deploying process: "
2796:                                + processDefinition.getName());
2797:
2798:                i_context.deployProcessDefinition(processDefinition);
2799:                zis.close();
2800:
2801:                // to be able to find new process definition in the same
2802:                // http-request we should make flush here
2803:                i_context.getSession().flush();
2804:
2805:                logger.info("Deployed process " + processDefinition.getName()
2806:                        + " successfully");
2807:
2808:                return processDefinition;
2809:            }
2810:
2811:            /**
2812:             * Very specific method This code got from jBPM and used for image generation It should be used onli inside
2813:             * ProcessImageComponent
2814:             * 
2815:             * @param writer
2816:             * @param i_workflow
2817:             * @param i_task
2818:             * @param i_step
2819:             * @throws DocumentException
2820:             * @throws IOException
2821:             * @todo REFACTOR IT! it is currently ugly
2822:             */
2823:            public String writeWorkflowImageTable(final WorkflowTO i_workflow,
2824:                    final TaskTO i_task, final StepTO i_step)
2825:                    throws EmForgeException {
2826:
2827:                Writer writer = new StringWriter();
2828:
2829:                try {
2830:                    String currentTokenColor = "red";
2831:                    String childTokenColor = "blue";
2832:                    String tokenNameColor = "blue";
2833:
2834:                    byte[] gpdBytes = retrieveByteArrays(i_workflow, i_task,
2835:                            i_step);
2836:
2837:                    if (gpdBytes == null) {
2838:                        return null;
2839:                    }
2840:
2841:                    int borderWidth = 4;
2842:                    Element rootDiagramElement = DocumentHelper.parseText(
2843:                            new String(gpdBytes)).getRootElement();
2844:                    int[] boxConstraint;
2845:                    int[] imageDimension = extractImageDimension(rootDiagramElement);
2846:                    String imageLink = Helper.getPath()
2847:                            + "/processimage?"
2848:                            + WorkflowController.WORKFLOW_ID_ATTR
2849:                            + "="
2850:                            + getWorkflowImpl(i_workflow, i_task, i_step)
2851:                                    .getId();
2852:
2853:                    // Draw image for processInstance
2854:                    if (i_task != null) {
2855:                        ProcessInstance processInstance = (ProcessInstance) execute(new JbpmCallback() {
2856:
2857:                            public Object doInJbpm(JbpmContext context) {
2858:
2859:                                return context.getProcessInstance(i_task
2860:                                        .getId());
2861:                            }
2862:                        });
2863:                        List<Token> allTokens = new LinkedList<Token>();
2864:
2865:                        walkTokens(processInstance.getRootToken(), allTokens);
2866:
2867:                        writer
2868:                                .write("<div style='position:relative; background-image:url("
2869:                                        + imageLink
2870:                                        + "); width: "
2871:                                        + imageDimension[0]
2872:                                        + "px; height: "
2873:                                        + imageDimension[1] + "px;'>");
2874:                        writer.write("\n");
2875:
2876:                        for (int i = 0; i < allTokens.size(); i++) {
2877:                            Token token = allTokens.get(i);
2878:
2879:                            // check how many tokens are on teh same level (= having the same parent)
2880:                            int offset = i;
2881:                            if (i > 0) {
2882:                                while (offset > 0
2883:                                        && ((Token) allTokens.get(offset - 1))
2884:                                                .getParent().equals(
2885:                                                        token.getParent())) {
2886:                                    offset--;
2887:                                }
2888:                            }
2889:
2890:                            boxConstraint = extractBoxConstraint(
2891:                                    rootDiagramElement, token);
2892:
2893:                            // Adjust for borders
2894:                            boxConstraint[2] -= borderWidth * 2;
2895:                            boxConstraint[3] -= borderWidth * 2;
2896:
2897:                            writer
2898:                                    .write("<div style='position:absolute; left: "
2899:                                            + boxConstraint[0]
2900:                                            + "px; top: "
2901:                                            + boxConstraint[1] + "px; ");
2902:                            writer.write("\n");
2903:
2904:                            if (i == (allTokens.size() - 1)) {
2905:                                writer.write("border: " + currentTokenColor);
2906:                                writer.write("\n");
2907:                            } else {
2908:                                writer.write("border: " + childTokenColor);
2909:                                writer.write("\n");
2910:                            }
2911:
2912:                            writer.write(" " + borderWidth + "px groove; "
2913:                                    + "width: " + boxConstraint[2]
2914:                                    + "px; height: " + boxConstraint[3]
2915:                                    + "px;'>");
2916:                            writer.write("\n");
2917:
2918:                            if (token.getName() != null) {
2919:                                writer
2920:                                        .write("<span style='color:"
2921:                                                + tokenNameColor
2922:                                                + ";font-style:italic;position:absolute;left:"
2923:                                                + (boxConstraint[2] + 10)
2924:                                                + "px;top:"
2925:                                                + ((i - offset) * 20)
2926:                                                + ";'>&nbsp;" + token.getName()
2927:                                                + "</span>");
2928:                                writer.write("\n");
2929:                            }
2930:
2931:                            writer.write("</div>");
2932:                            writer.write("\n");
2933:                        }
2934:
2935:                        writer.write("</div>");
2936:                        writer.write("\n");
2937:                    } else if (i_step != null) {
2938:                        TaskInstance taskInstance = (TaskInstance) execute(new JbpmCallback() {
2939:
2940:                            public Object doInJbpm(JbpmContext context) {
2941:
2942:                                return context.getTaskInstance(i_step.getId());
2943:                            }
2944:                        });
2945:
2946:                        boxConstraint = extractBoxConstraint(
2947:                                rootDiagramElement, taskInstance);
2948:
2949:                        writer
2950:                                .write("<table border=0 cellspacing=0 cellpadding=0 width="
2951:                                        + imageDimension[0]
2952:                                        + " height="
2953:                                        + imageDimension[1] + ">");
2954:                        writer.write("\n");
2955:                        writer.write("  <tr>");
2956:                        writer.write("\n");
2957:                        writer.write("    <td width=" + imageDimension[0]
2958:                                + "px height=" + imageDimension[1]
2959:                                + "px style=\"background-image:url("
2960:                                + imageLink + ")\" valign=top>");
2961:                        writer.write("\n");
2962:                        writer
2963:                                .write("      <table border=0 cellspacing=0 cellpadding=0 style=\"border-width:0px; background-color:transparent;\">");
2964:                        writer.write("\n");
2965:                        writer.write("        <tr>");
2966:                        writer.write("\n");
2967:                        writer
2968:                                .write("          <td width="
2969:                                        + (boxConstraint[0] - borderWidth)
2970:                                        + " height="
2971:                                        + (boxConstraint[1] - borderWidth)
2972:                                        + " style=\"background-color:transparent;\" border=0></td>");
2973:                        writer.write("\n");
2974:                        writer.write("        </tr>");
2975:                        writer.write("\n");
2976:                        writer.write("        <tr>");
2977:                        writer.write("\n");
2978:                        writer
2979:                                .write("          <td style=\"background-color:transparent;\" border=0></td>");
2980:                        writer.write("\n");
2981:                        writer
2982:                                .write("          <td style=\"border-color:"
2983:                                        + currentTokenColor
2984:                                        + "; border-width:"
2985:                                        + borderWidth
2986:                                        + "px; border-style:groove; background-color:transparent;\" width="
2987:                                        + boxConstraint[2]
2988:                                        + " height="
2989:                                        + (boxConstraint[3] + (2 * borderWidth))
2990:                                        + ">&nbsp;</td>");
2991:                        writer.write("\n");
2992:                        writer.write("        </tr>");
2993:                        writer.write("\n");
2994:                        writer.write("      </table>");
2995:                        writer.write("\n");
2996:                        writer.write("    </td>");
2997:                        writer.write("\n");
2998:                        writer.write("  </tr>");
2999:                        writer.write("\n");
3000:                        writer.write("</table>");
3001:                        writer.write("\n");
3002:                    } else if (i_task == null && i_workflow != null) {
3003:                        // / @todo maybe change to image tag
3004:                        writer
3005:                                .write("<div style='position:relative; background-image:url("
3006:                                        + imageLink
3007:                                        + "); width: "
3008:                                        + imageDimension[0]
3009:                                        + "px; height: "
3010:                                        + imageDimension[1] + "px;'></div>");
3011:                        writer.write("\n");
3012:                    }
3013:
3014:                    return writer.toString();
3015:                } catch (Exception ex) {
3016:                    throw new EmForgeException(
3017:                            "Cannot generate workflow image", ex);
3018:                }
3019:            }
3020:
3021:            /**
3022:             * @param i_workflow
3023:             * @param i_task
3024:             * @param i_step
3025:             * @return
3026:             */
3027:            private byte[] retrieveByteArrays(WorkflowTO i_workflow,
3028:                    TaskTO i_task, StepTO i_step) {
3029:
3030:                try {
3031:                    ProcessDefinition processDef = getWorkflowImpl(i_workflow,
3032:                            i_task, i_step);
3033:                    FileDefinition fileDefinition = processDef
3034:                            .getFileDefinition();
3035:                    return fileDefinition.getBytes("gpd.xml");
3036:                } catch (Exception e) {
3037:                    logger.error("Cannot get process def gdp.xml", e);
3038:                    return null;
3039:                }
3040:            }
3041:
3042:            /**
3043:             * @param i_workflow
3044:             * @param i_task
3045:             * @param i_step
3046:             * @return
3047:             */
3048:            private ProcessDefinition getWorkflowImpl(
3049:                    final WorkflowTO i_workflow, final TaskTO i_task,
3050:                    final StepTO i_step) {
3051:
3052:                ProcessDefinition processDef = (ProcessDefinition) execute(new JbpmCallback() {
3053:
3054:                    public Object doInJbpm(JbpmContext context) {
3055:
3056:                        if (i_workflow != null) {
3057:                            return context.getGraphSession()
3058:                                    .getProcessDefinition(i_workflow.getId());
3059:                        }
3060:
3061:                        if (i_task != null) {
3062:                            return getProcessDef(context, i_task
3063:                                    .getWorkflowName(), i_task
3064:                                    .getWorkflowVersion());
3065:                        }
3066:
3067:                        if (i_step != null) {
3068:                            return getProcessDef(context, i_step
3069:                                    .getWorkflowName(), i_step
3070:                                    .getWorkflowVersion());
3071:                        }
3072:
3073:                        return null;
3074:                    }
3075:                });
3076:
3077:                return processDef;
3078:            }
3079:
3080:            /**
3081:             * @param root
3082:             * @param i_taskInstance
3083:             * @return
3084:             */
3085:            private int[] extractBoxConstraint(Element root,
3086:                    TaskInstance i_taskInstance) {
3087:
3088:                int[] result = new int[4];
3089:                try {
3090:                    String nodeName = i_taskInstance.getToken().getNode()
3091:                            .getName();
3092:                    XPath xPath = new DefaultXPath("//node[@name='" + nodeName
3093:                            + "']");
3094:                    Element node = (Element) xPath.selectSingleNode(root);
3095:                    result[0] = Integer.valueOf(node.attribute("x").getValue())
3096:                            .intValue();
3097:                    result[1] = Integer.valueOf(node.attribute("y").getValue())
3098:                            .intValue();
3099:                    result[2] = Integer.valueOf(
3100:                            node.attribute("width").getValue()).intValue();
3101:
3102:                    // [AKA] Fixed (probably incorrectly problem with -1 in the width
3103:                    if (result[2] == -1) {
3104:                        result[2] = 150;
3105:                    }
3106:
3107:                    result[3] = Integer.valueOf(
3108:                            node.attribute("height").getValue()).intValue();
3109:                } catch (Exception ex) {
3110:                    // due to some problems with incorrect process definition we can get errors here
3111:                    // but still - we should be able to display image
3112:                    logger.error("Cannot get box contraints", ex);
3113:                    result[0] = 0;
3114:                    result[1] = 0;
3115:                    result[2] = 0;
3116:                    result[3] = 0;
3117:                }
3118:                return result;
3119:            }
3120:
3121:            /**
3122:             * @param root
3123:             * @param token
3124:             * @return
3125:             */
3126:            private int[] extractBoxConstraint(Element root, Token token) {
3127:
3128:                int[] result = new int[4];
3129:                try {
3130:                    String nodeName = token.getNode().getName();
3131:                    XPath xPath = new DefaultXPath("//node[@name=" + '"'
3132:                            + nodeName + '"' + "]");
3133:                    Element node = (Element) xPath.selectSingleNode(root);
3134:                    result[0] = Integer.valueOf(node.attribute("x").getValue())
3135:                            .intValue();
3136:                    result[1] = Integer.valueOf(node.attribute("y").getValue())
3137:                            .intValue();
3138:                    result[2] = Integer.valueOf(
3139:                            node.attribute("width").getValue()).intValue();
3140:                    result[3] = Integer.valueOf(
3141:                            node.attribute("height").getValue()).intValue();
3142:                } catch (Exception ex) {
3143:                    // due to some problems with incorrect process definition we can get errors here
3144:                    // but still - we should be able to display image
3145:                    logger.error("Cannot get box contraints", ex);
3146:                    result[0] = 0;
3147:                    result[1] = 0;
3148:                    result[2] = 0;
3149:                    result[3] = 0;
3150:                }
3151:                return result;
3152:            }
3153:
3154:            /**
3155:             * @param root
3156:             * @return
3157:             */
3158:            private int[] extractImageDimension(Element root) {
3159:
3160:                int[] result = new int[2];
3161:                result[0] = Integer.valueOf(root.attribute("width").getValue())
3162:                        .intValue();
3163:                result[1] = Integer
3164:                        .valueOf(root.attribute("height").getValue())
3165:                        .intValue();
3166:                return result;
3167:            }
3168:
3169:            /**
3170:             * @param i_parent
3171:             * @param o_allTokens
3172:             */
3173:            @SuppressWarnings("unchecked")
3174:            private void walkTokens(Token i_parent,
3175:                    Collection<Token> o_allTokens) {
3176:
3177:                Map<Object, Token> children = i_parent.getChildren();
3178:                if (children != null && children.size() > 0) {
3179:                    for (Token child : children.values()) {
3180:                        walkTokens(child, o_allTokens);
3181:                    }
3182:                }
3183:
3184:                o_allTokens.add(i_parent);
3185:            }
3186:
3187:            /**
3188:             * Method used in Process Icon Servlet
3189:             * 
3190:             * @param workflowId
3191:             * @return
3192:             */
3193:            public byte[] getWorkflowIcon(final long workflowId) {
3194:
3195:                byte[] icon = (byte[]) execute(new JbpmCallback() {
3196:
3197:                    public Object doInJbpm(JbpmContext context) {
3198:
3199:                        ProcessDefinition processDef = getProcessDef(context,
3200:                                workflowId);
3201:
3202:                        if (processDef == null) {
3203:                            return null;
3204:                        }
3205:
3206:                        return ProcessDefTransformer
3207:                                .getWorkflowIcon(processDef);
3208:                    }
3209:                });
3210:
3211:                return icon;
3212:
3213:            }
3214:
3215:            /**
3216:             * Returns workflow image
3217:             * 
3218:             * @param workflowId
3219:             * @return
3220:             */
3221:            public byte[] getWorkflowImage(final long workflowId) {
3222:
3223:                byte[] icon = (byte[]) execute(new JbpmCallback() {
3224:
3225:                    public Object doInJbpm(JbpmContext context) {
3226:
3227:                        ProcessDefinition processDef = getProcessDef(context,
3228:                                workflowId);
3229:
3230:                        if (processDef == null) {
3231:                            return null;
3232:                        }
3233:
3234:                        return ProcessDefTransformer
3235:                                .getWorkflowImage(processDef);
3236:                    }
3237:                });
3238:
3239:                return icon;
3240:
3241:            }
3242:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.