001/*
002 *  Copyright 2017 Anyware Services
003 *
004 *  Licensed under the Apache License, Version 2.0 (the "License");
005 *  you may not use this file except in compliance with the License.
006 *  You may obtain a copy of the License at
007 *
008 *      http://www.apache.org/licenses/LICENSE-2.0
009 *
010 *  Unless required by applicable law or agreed to in writing, software
011 *  distributed under the License is distributed on an "AS IS" BASIS,
012 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 *  See the License for the specific language governing permissions and
014 *  limitations under the License.
015 */
016package org.ametys.plugins.bpm.process;
017
018import java.io.IOException;
019import java.util.ArrayList;
020import java.util.Collections;
021import java.util.Comparator;
022import java.util.List;
023import java.util.Set;
024
025import org.apache.avalon.framework.context.Context;
026import org.apache.avalon.framework.context.ContextException;
027import org.apache.avalon.framework.context.Contextualizable;
028import org.apache.avalon.framework.service.ServiceException;
029import org.apache.avalon.framework.service.ServiceManager;
030import org.apache.cocoon.ProcessingException;
031import org.apache.cocoon.components.ContextHelper;
032import org.apache.cocoon.environment.Request;
033import org.apache.cocoon.generation.ServiceableGenerator;
034import org.apache.cocoon.xml.AttributesImpl;
035import org.apache.cocoon.xml.XMLUtils;
036import org.xml.sax.SAXException;
037
038import org.ametys.core.user.CurrentUserProvider;
039import org.ametys.core.user.User;
040import org.ametys.core.user.UserIdentity;
041import org.ametys.core.user.UserManager;
042import org.ametys.core.util.DateUtils;
043import org.ametys.plugins.bpm.BPMWorkflowManager;
044import org.ametys.plugins.bpm.jcr.JCRWorkflow;
045import org.ametys.plugins.bpm.jcr.JCRWorkflowProcess;
046import org.ametys.plugins.core.user.UserHelper;
047import org.ametys.plugins.repository.AmetysObjectResolver;
048import org.ametys.plugins.repository.AmetysRepositoryException;
049import org.ametys.plugins.workflow.support.WorkflowProvider;
050import org.ametys.plugins.workflow.support.WorkflowProvider.AmetysObjectWorkflow;
051
052import com.opensymphony.workflow.loader.StepDescriptor;
053import com.opensymphony.workflow.loader.WorkflowDescriptor;
054import com.opensymphony.workflow.spi.WorkflowEntry;
055
056/**
057 * Generator for the processes dashboard service
058 */
059public class ProcessesDashboardGenerator extends ServiceableGenerator implements Contextualizable
060{
061    
062    private BPMWorkflowManager _bpmWorkflowManager;
063    private AmetysObjectResolver _resolver;
064    private WorkflowProvider _workflowProvider;
065    private CurrentUserProvider _currentUserProvider;
066    private UserManager _userManager;
067    private UserHelper _userHelper;
068    private Context _context;
069    
070    public void contextualize(Context context) throws ContextException
071    {
072        _context = context;
073    }
074    
075    @Override
076    public void service(ServiceManager smanager) throws ServiceException
077    {
078        super.service(smanager);
079        _bpmWorkflowManager = (BPMWorkflowManager) smanager.lookup(BPMWorkflowManager.ROLE);
080        _resolver = (AmetysObjectResolver) smanager.lookup(AmetysObjectResolver.ROLE);
081        _workflowProvider = (WorkflowProvider) smanager.lookup(WorkflowProvider.ROLE);
082        _currentUserProvider = (CurrentUserProvider) smanager.lookup(CurrentUserProvider.ROLE);
083        _userManager = (UserManager) smanager.lookup(UserManager.ROLE);
084        _userHelper = (UserHelper) smanager.lookup(UserHelper.ROLE);
085    }
086
087    public void generate() throws IOException, SAXException, ProcessingException
088    {
089        Request request = ContextHelper.getRequest(_context);
090        String siteName = (String)  request.getAttribute("site");
091        String lang = (String) request.getAttribute("sitemapLanguage");
092        
093        contentHandler.startDocument();
094        
095        AttributesImpl attrs = new AttributesImpl();
096        String templateForProcessPage = _bpmWorkflowManager.getTemplateForProcessPage(siteName, lang);
097        attrs.addCDATAAttribute("processTemplate", templateForProcessPage);
098        XMLUtils.startElement(contentHandler, "processesDashboard", attrs);
099
100        Set<JCRWorkflowProcess> processes = _bpmWorkflowManager.getUserProcesses();
101        if (processes.size() > 0)
102        {
103            List<JCRWorkflowProcess> processesList = new ArrayList<>(processes);
104            Collections.sort(processesList, new Comparator<JCRWorkflowProcess>()
105            {
106                @Override
107                public int compare(JCRWorkflowProcess p1, JCRWorkflowProcess p2)
108                {
109                    return -p1.getCreationDate().compareTo(p2.getCreationDate());
110                }
111            });
112            _saxProcesses(processesList);
113        }
114        
115        XMLUtils.endElement(contentHandler, "processesDashboard");
116
117        contentHandler.endDocument();
118    }
119    
120    private void _saxProcesses(List<JCRWorkflowProcess> processesList) throws SAXException
121    {
122        XMLUtils.startElement(contentHandler, "processes");
123
124        for (JCRWorkflowProcess process : processesList)
125        {
126            _saxProcess(process);
127        }
128        
129        XMLUtils.endElement(contentHandler, "processes");
130    }
131
132    private void _saxProcess(JCRWorkflowProcess process) throws SAXException 
133    {
134        JCRWorkflow workflow = _resolver.resolveById(process.getWorkflow());
135        UserIdentity creator = process.getCreator();
136        User user = _userManager.getUser(creator);
137        
138        AttributesImpl attrs = new AttributesImpl();
139        attrs.addCDATAAttribute("id", process.getId());
140        attrs.addCDATAAttribute("name", process.getName());
141        attrs.addCDATAAttribute("title", process.getTitle());
142        attrs.addCDATAAttribute("isCreator", creator.equals(_currentUserProvider.getUser()) ? "true" : "false");
143        XMLUtils.startElement(contentHandler, "process", attrs);
144        
145        attrs = new AttributesImpl();
146        attrs.addCDATAAttribute("id", workflow.getId());
147        attrs.addCDATAAttribute("name", workflow.getName());
148        attrs.addCDATAAttribute("title", workflow.getTitle());
149        XMLUtils.createElement(contentHandler, "workflow", attrs);
150        
151        if (user != null)
152        {
153            _userHelper.saxUser(user, contentHandler, "creator");
154        }
155        XMLUtils.createElement(contentHandler, "creationDate", DateUtils.dateToString(process.getCreationDate()));
156        
157        try
158        {
159            AmetysObjectWorkflow aoWorkflow = _workflowProvider.getAmetysObjectWorkflow(process, true);
160            String workflowName = aoWorkflow.getWorkflowName(process.getWorkflowId());
161            if (workflowName != null)
162            {
163                WorkflowDescriptor workflowDescriptor = aoWorkflow.getWorkflowDescriptor(workflowName);
164                StepDescriptor step = workflowDescriptor.getStep((int) process.getCurrentStepId());
165                attrs = new AttributesImpl();
166                int entryState = aoWorkflow.getEntryState(process.getWorkflowId());
167                attrs.addCDATAAttribute("completed", entryState ==  WorkflowEntry.COMPLETED ? "true" : "false");
168                XMLUtils.createElement(contentHandler, "currentStep", attrs, step.getName());
169            }
170        }
171        catch (AmetysRepositoryException e)
172        {
173            // workflow not found
174            getLogger().warn("Unable to sax workflow for process '" + process.getTitle() + "[" + process.getId() + "]'", e);
175        }
176
177        XMLUtils.endElement(contentHandler, "process");
178    }
179}