001/*
002 *  Copyright 2011 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.HashMap;
019import java.util.Map;
020
021import javax.jcr.Node;
022import javax.jcr.Repository;
023import javax.jcr.RepositoryException;
024import javax.jcr.Session;
025
026import org.apache.avalon.framework.parameters.Parameters;
027import org.apache.avalon.framework.service.ServiceException;
028import org.apache.avalon.framework.service.ServiceManager;
029import org.apache.cocoon.environment.ObjectModelHelper;
030import org.apache.cocoon.environment.Redirector;
031import org.apache.cocoon.environment.Request;
032import org.apache.commons.lang.ArrayUtils;
033
034import org.ametys.cms.ObservationConstants;
035import org.ametys.cms.repository.CloneComponent;
036import org.ametys.cms.repository.Content;
037import org.ametys.cms.repository.RequestAttributeWorkspaceSelector;
038import org.ametys.cms.repository.WorkflowAwareContent;
039import org.ametys.core.observation.Event;
040import org.ametys.core.observation.ObservationManager;
041import org.ametys.core.user.UserIdentity;
042import org.ametys.plugins.repository.AmetysObjectResolver;
043import org.ametys.plugins.repository.provider.AbstractRepository;
044import org.ametys.plugins.repository.version.VersionableAmetysObject;
045import org.ametys.plugins.workflow.support.WorkflowProvider.AmetysObjectWorkflow;
046
047import com.opensymphony.workflow.InvalidInputException;
048import com.opensymphony.workflow.WorkflowException;
049
050/**
051 * Unarchive a content.
052 */
053public class UnarchiveContentAction extends ContentWorkflowAction
054{
055    /** The repository. */
056    protected Repository _repository;
057    
058    /** The ametys object resolver. */
059    protected AmetysObjectResolver _resolver;
060    
061    /** The clone component. */
062    protected CloneComponent _cloneComponent;
063    
064    /** Observation manager available to subclasses. */
065    protected ObservationManager _observationManager;
066    
067    @Override
068    public void service(ServiceManager serviceManager) throws ServiceException
069    {
070        super.service(serviceManager);
071        _repository = (Repository) serviceManager.lookup(AbstractRepository.ROLE);
072        _resolver = (AmetysObjectResolver) serviceManager.lookup(AmetysObjectResolver.ROLE);
073        _cloneComponent = (CloneComponent) serviceManager.lookup(CloneComponent.ROLE);
074        _observationManager = (ObservationManager) serviceManager.lookup(ObservationManager.ROLE);
075    }
076    
077    @Override
078    protected Map<String, String> _act(Redirector redirector, Map objectModel, String source, Parameters parameters, int actionId, Map inputs) throws InvalidInputException, WorkflowException
079    {
080        Request request = ObjectModelHelper.getRequest(objectModel);
081        
082        WorkflowAwareContent archivedContent = _getContent(objectModel);
083        UserIdentity user = _getUser(objectModel);
084        
085        String contentId = archivedContent.getId();
086        
087        try
088        {
089            // Move the content and its workflow back to the default workspace.
090            unarchiveContent(archivedContent);
091            
092            // Resolve the content in the default workspace.
093            RequestAttributeWorkspaceSelector.setForcedWorkspace(request, "default");
094            WorkflowAwareContent content = _resolver.resolveById(contentId);
095            
096            if (content instanceof VersionableAmetysObject)
097            {
098                ((VersionableAmetysObject) content).checkpoint();
099            }
100            
101            request.setAttribute(Content.class.getName(), content);
102            inputs.put(AbstractContentWorkflowComponent.CONTENT_KEY, content);
103            
104            // Trigger the action.
105            Map<String, String> result = super._act(redirector, objectModel, source, parameters, actionId, inputs);
106            
107            // Notify that a content has been added to the default workspace.
108            Map<String, Object> eventParams = new HashMap<>();
109            eventParams.put(ObservationConstants.ARGS_CONTENT, content);
110            eventParams.put(ObservationConstants.ARGS_CONTENT_ID, contentId);
111            
112            _observationManager.notify(new Event(ObservationConstants.EVENT_CONTENT_ADDED, user, eventParams));
113            
114            return result;
115        }
116        catch (RepositoryException e)
117        {
118            throw new WorkflowException("Error unarchiving the content " + contentId, e);
119        }
120    }
121    
122    /**
123     * Test if the action can be executed.
124     * @param content the content
125     * @param actionId the action ID.
126     * @param inputs the workflow inputs.
127     * @return true if the action is valid in the current environment, false otherwise.
128     */
129    protected boolean isActionValid(WorkflowAwareContent content, int actionId, Map inputs)
130    {
131        long workflowId = content.getWorkflowId();
132        
133        AmetysObjectWorkflow workflow = _workflowProvider.getAmetysObjectWorkflow(content);
134        int[] availableActions = workflow.getAvailableActions(workflowId, inputs);
135        
136        return ArrayUtils.contains(availableActions, actionId);
137    }
138    
139    /**
140     * Unarchive a content.
141     * @param content the content (in the archives workspace).
142     * @throws RepositoryException If an error occurred
143     */
144    protected void unarchiveContent(WorkflowAwareContent content) throws RepositoryException
145    {
146        Session defaultSession = null;
147        Session archiveSession = null;
148        
149        try
150        {
151            // Open a session on the default workspace.
152            defaultSession = _repository.login("default");
153            
154            // The content node in the archives workspace.
155            Node contentNode = content.getNode();
156            archiveSession = contentNode.getSession();
157            
158            // Clone the content in the default workspace.
159            _cloneComponent.cloneContentNodeWithWorkflow(defaultSession, contentNode);
160            
161            // Remove the content in the archives workspace.
162            content.remove();
163            
164            // Save everything.
165            defaultSession.save();
166            archiveSession.save();
167        }
168        finally
169        {
170            if (defaultSession != null)
171            {
172                defaultSession.logout();
173            }
174        }
175    }
176}