001/*
002 *  Copyright 2013 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.RepositoryException;
023import javax.jcr.lock.Lock;
024import javax.jcr.lock.LockManager;
025
026import org.apache.avalon.framework.activity.Initializable;
027
028import org.ametys.cms.ObservationConstants;
029import org.ametys.cms.repository.WorkflowAwareContent;
030import org.ametys.core.observation.Event;
031import org.ametys.core.observation.ObservationManager;
032import org.ametys.plugins.repository.RepositoryConstants;
033import org.ametys.plugins.repository.lock.LockAwareAmetysObject;
034import org.ametys.plugins.repository.version.VersionableAmetysObject;
035import org.ametys.plugins.workflow.support.WorkflowProvider;
036import org.ametys.plugins.workflow.support.WorkflowProvider.AmetysObjectWorkflow;
037
038import com.opensymphony.workflow.FunctionProvider;
039import com.opensymphony.workflow.WorkflowException;
040import com.opensymphony.workflow.spi.Step;
041
042/**
043 * Abstract workflow function working on a Content, which provides common content methods.
044 */
045public abstract class AbstractContentFunction extends AbstractContentWorkflowComponent implements FunctionProvider, Initializable
046{
047    
048    /** The workflow provider. */
049    protected WorkflowProvider _workflowProvider;
050    /** The observation manager */
051    protected ObservationManager _observationManager;
052
053    @Override
054    public void initialize() throws Exception
055    {
056        _workflowProvider = (WorkflowProvider) _manager.lookup(WorkflowProvider.ROLE);
057        _observationManager = (ObservationManager) _manager.lookup(ObservationManager.ROLE);
058    }
059    
060    /**
061     * Add the content lock token to the current session if the content is locked.
062     * @param content the content.
063     * @throws WorkflowException if an error occurs.
064     * @throws RepositoryException if a repository error occurs.
065     */
066    protected void _addLockToken(WorkflowAwareContent content) throws WorkflowException, RepositoryException
067    {
068        if (content != null && content instanceof LockAwareAmetysObject)
069        {
070            LockAwareAmetysObject lockAwareContent = (LockAwareAmetysObject) content;
071            if (lockAwareContent.isLocked())
072            {
073                Node node = content.getNode();
074                
075                LockManager lockManager = node.getSession().getWorkspace().getLockManager();
076                
077                Lock lock = lockManager.getLock(node.getPath());
078                Node lockHolder = lock.getNode();
079                
080                lockManager.addLockToken(lockHolder.getProperty(RepositoryConstants.METADATA_LOCKTOKEN).getString());
081            }
082        }
083    }
084    
085    /**
086     * Set the content's current step ID without notifying the observers that the content's workflow has changed.
087     * @param content the content.
088     * @param transientVars The workflow transient vars.
089     * @throws WorkflowException if an error occurs.
090     */
091    protected void _setCurrentStepId(WorkflowAwareContent content, Map transientVars) throws WorkflowException
092    {
093        if (content != null)
094        {
095            // Save the current step.
096            AmetysObjectWorkflow workflow = _workflowProvider.getAmetysObjectWorkflow(content);
097            Step currentStep = (Step) workflow.getCurrentSteps(content.getWorkflowId()).iterator().next();
098            content.setCurrentStepId(currentStep.getStepId());
099            content.saveChanges();
100        }
101    }
102    
103    /**
104     * Set the content's current step ID and notify the observers that the content's workflow has changed.
105     * @param content the content.
106     * @param transientVars The workflow transient vars.
107     * @throws WorkflowException if an error occurs.
108     */
109    protected void _setCurrentStepIdAndNotify(WorkflowAwareContent content, Map transientVars) throws WorkflowException
110    {
111        if (content != null)
112        {
113            // Save the current step.
114            AmetysObjectWorkflow workflow = _workflowProvider.getAmetysObjectWorkflow(content);
115            Step currentStep = (Step) workflow.getCurrentSteps(content.getWorkflowId()).iterator().next();
116            content.setCurrentStepId(currentStep.getStepId());
117            content.saveChanges();
118            
119            Map<String, Object> eventParams = new HashMap<>();
120            eventParams.put(ObservationConstants.ARGS_CONTENT, content);
121            eventParams.put(ObservationConstants.ARGS_CONTENT_ID, content.getId());
122            _observationManager.notify(new Event(ObservationConstants.EVENT_CONTENT_WORKFLOW_CHANGED, getUser(transientVars), eventParams));
123        }
124    }
125    
126    /**
127     * Persists the current version and create a new one.
128     * @param content the content.
129     * @throws WorkflowException if an error occurs.
130     */
131    protected void _createVersion(WorkflowAwareContent content) throws WorkflowException
132    {
133        if (content != null)
134        {
135            // Create a new version
136            if (content instanceof VersionableAmetysObject)
137            {
138                ((VersionableAmetysObject) content).checkpoint();
139            }
140        }
141    }
142    
143    /**
144     * Add a label on the content.
145     * @param content the content.
146     * @param label the label to add.
147     * @throws WorkflowException if an error occurs.
148     * @throws RepositoryException if an error occurs.
149     */
150    protected void _addLabel(WorkflowAwareContent content, String label) throws WorkflowException, RepositoryException
151    {
152        if (content != null)
153        {
154            if (content instanceof VersionableAmetysObject)
155            {
156                ((VersionableAmetysObject) content).addLabel(label, true);
157            }
158        }
159    }
160    
161}