001/*
002 *  Copyright 2015 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.cms.workflow;
017
018import java.util.ArrayList;
019import java.util.HashMap;
020import java.util.HashSet;
021import java.util.List;
022import java.util.Map;
023import java.util.Set;
024
025import javax.jcr.Node;
026import javax.jcr.RepositoryException;
027import javax.jcr.Session;
028
029import org.apache.avalon.framework.parameters.Parameters;
030import org.apache.avalon.framework.service.ServiceException;
031import org.apache.avalon.framework.service.ServiceManager;
032import org.apache.cocoon.ProcessingException;
033import org.apache.cocoon.environment.ObjectModelHelper;
034import org.apache.cocoon.environment.Redirector;
035import org.apache.cocoon.environment.Request;
036import org.apache.cocoon.environment.SourceResolver;
037
038import org.ametys.cms.content.ContentHelper;
039import org.ametys.cms.repository.Content;
040import org.ametys.cms.repository.WorkflowAwareContent;
041import org.ametys.cms.workflow.history.ElementWithWorkflow;
042import org.ametys.cms.workflow.history.HistoryStep;
043import org.ametys.cms.workflow.history.VersionInformation;
044import org.ametys.cms.workflow.history.WorkflowHistory;
045import org.ametys.cms.workflow.history.WorkflowHistoryHelper;
046import org.ametys.core.cocoon.JSonReader;
047import org.ametys.core.right.RightManager;
048import org.ametys.core.right.RightManager.RightResult;
049import org.ametys.plugins.repository.version.VersionAwareAmetysObject;
050import org.ametys.plugins.workflow.store.AbstractJackrabbitWorkflowStore;
051import org.ametys.plugins.workflow.support.WorkflowProvider;
052import org.ametys.plugins.workflow.support.WorkflowProvider.AmetysObjectWorkflow;
053
054/**
055 * This action returns the workflow history of a content
056 *
057 */
058public class ContentHistoryAction extends ContentVersionHistoryAction
059{
060    /** The workflow provider */
061    protected WorkflowProvider _workflowProvider;
062
063    /** The content helper */
064    protected ContentHelper _contentHelper;
065
066    /** The workflow history helper */
067    protected WorkflowHistoryHelper _workflowHistoryHelper;
068
069    /** The right manager */
070    protected RightManager _rightManager;
071    
072    @Override
073    public void service(ServiceManager serviceManager) throws ServiceException
074    {
075        super.service(serviceManager);
076        _workflowProvider = (WorkflowProvider) serviceManager.lookup(WorkflowProvider.ROLE);
077        _contentHelper = (ContentHelper) serviceManager.lookup(ContentHelper.ROLE);
078        _workflowHistoryHelper = (WorkflowHistoryHelper) serviceManager.lookup(WorkflowHistoryHelper.ROLE);
079        _rightManager = (RightManager) serviceManager.lookup(RightManager.ROLE);
080    }
081
082    @Override
083    public Map act(Redirector redirector, SourceResolver resolver, Map objectModel, String source, Parameters parameters) throws Exception
084    {
085        Request request = ObjectModelHelper.getRequest(objectModel);
086
087        String id = request.getParameter("contentId");
088        Content content = _resolver.resolveById(id);
089        
090        Map<String, Object> result = new HashMap<>();
091        if (_rightManager.currentUserHasRight("CMS_Rights_Content_History", content) == RightResult.RIGHT_ALLOW)
092        {
093            List<Map<String, Object>> workflowSteps = new ArrayList<>();
094            
095            Set<String> validatedVersions = new HashSet<>();
096            
097            try
098            {
099                if (content instanceof WorkflowAwareContent && content instanceof VersionAwareAmetysObject)
100                {
101                    WorkflowAwareContent workflowAwareContent = (WorkflowAwareContent) content;
102                    
103                    AmetysObjectWorkflow workflow = _workflowProvider.getAmetysObjectWorkflow(workflowAwareContent);
104                    long workflowId = workflowAwareContent.getWorkflowId();
105                    int initialActionId = (int) _getInitialActionId(workflow, workflowAwareContent);
106                    
107                    List<VersionInformation> versionsInformation = _resolveVersionInformations((VersionAwareAmetysObject) content);
108                    ElementWithWorkflow element = new ElementWithWorkflow(
109                            _contentHelper.getTitle(content), 
110                            workflowAwareContent.getCreationDate(), 
111                            workflowAwareContent.getCreator(),
112                            versionsInformation
113                            );
114                    
115                    WorkflowHistory workflowHistory = _workflowHistoryHelper.getWorkflowHistory(element, workflowId, workflow, initialActionId);
116                    for (HistoryStep step : workflowHistory.getSteps())
117                    {
118                        workflowSteps.add(_workflowHistoryHelper.historyStep2Json(step));
119                    }
120                    validatedVersions = workflowHistory.getValidatedVersions();
121                }
122            }
123            catch (RepositoryException e)
124            {
125                throw new ProcessingException("Unable to access version history", e);
126            }
127            
128            for (Map<String, Object> stepInfo : workflowSteps)
129            {
130                @SuppressWarnings("unchecked")
131                List<Map<String, Object>> versions = (List<Map<String, Object>>) stepInfo.get("versions");
132                
133                for (Map<String, Object> version : versions)
134                {
135                    String versionName = (String) version.get("name");
136                    if (validatedVersions.contains(versionName))
137                    {
138                        version.put("valid", true);
139                    }
140                }
141            }
142            
143            result.put("workflow", workflowSteps);
144        }
145        else
146        {
147            result.put("hasRight", false);
148        }
149        request.setAttribute(JSonReader.OBJECT_TO_READ, result);
150        return EMPTY_MAP;
151    }
152
153    private long _getInitialActionId(AmetysObjectWorkflow workflow, WorkflowAwareContent waContent)
154    {
155        try
156        {
157            Session session = waContent.getNode().getSession();
158            AbstractJackrabbitWorkflowStore workflowStore = (AbstractJackrabbitWorkflowStore) workflow.getConfiguration().getWorkflowStore();
159            Node workflowEntryNode = workflowStore.getEntryNode(session, waContent.getWorkflowId());
160            return workflowEntryNode.getProperty("ametys-internal:initialActionId").getLong();
161        }
162        catch (Exception e)
163        {
164            getLogger().error("Unable to retrieves initial action id for workflow aware content : " + waContent.getId(), e);
165            return 0;
166        }
167    }
168}