001/*
002 *  Copyright 2010 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.content;
017
018import java.io.IOException;
019import java.util.ArrayList;
020import java.util.List;
021import java.util.Map;
022import java.util.Set;
023
024import org.apache.avalon.framework.service.ServiceException;
025import org.apache.avalon.framework.service.ServiceManager;
026import org.apache.cocoon.ProcessingException;
027import org.apache.cocoon.environment.ObjectModelHelper;
028import org.apache.cocoon.generation.ServiceableGenerator;
029import org.apache.cocoon.xml.AttributesImpl;
030import org.apache.cocoon.xml.XMLUtils;
031import org.apache.commons.lang.ArrayUtils;
032import org.apache.commons.lang.StringUtils;
033import org.xml.sax.SAXException;
034
035import org.ametys.cms.lock.LockContentManager;
036import org.ametys.cms.repository.Content;
037import org.ametys.cms.repository.ModifiableContent;
038import org.ametys.cms.repository.WorkflowAwareContent;
039import org.ametys.cms.workflow.ContentWorkflowHelper;
040import org.ametys.core.right.RightManager;
041import org.ametys.core.user.CurrentUserProvider;
042import org.ametys.core.user.UserIdentity;
043import org.ametys.core.util.DateUtils;
044import org.ametys.plugins.repository.AmetysObjectResolver;
045import org.ametys.plugins.repository.UnknownAmetysObjectException;
046import org.ametys.plugins.repository.lock.LockAwareAmetysObject;
047import org.ametys.plugins.workflow.support.WorkflowProvider;
048import org.ametys.plugins.workflow.support.WorkflowProvider.AmetysObjectWorkflow;
049
050import com.opensymphony.workflow.spi.Step;
051
052/**
053 * SAX the contents information
054 */
055public class ContentInformationGenerator extends ServiceableGenerator
056{
057    /** Ametys object resovler. */
058    protected AmetysObjectResolver _resolver;
059    /** The rights manager */
060    protected RightManager _rightManager;
061    /** The user provider */
062    protected CurrentUserProvider _userProvider;
063    /** The workflow provider */
064    protected WorkflowProvider _workflowProvider;
065    /** The lock manager. */
066    protected LockContentManager _lockManager;
067    /** The content workflow helper */
068    protected ContentWorkflowHelper _contentWorkflowHelper;
069    /** The content helper */
070    protected ContentHelper _contentHelper;
071
072    @Override
073    public void service(ServiceManager serviceManager) throws ServiceException
074    {
075        super.service(serviceManager);
076        _resolver = (AmetysObjectResolver) serviceManager.lookup(AmetysObjectResolver.ROLE);
077        _userProvider = (CurrentUserProvider) serviceManager.lookup(CurrentUserProvider.ROLE);
078        _rightManager = (RightManager) serviceManager.lookup(RightManager.ROLE);
079        _workflowProvider = (WorkflowProvider) serviceManager.lookup(WorkflowProvider.ROLE);
080        _lockManager = (LockContentManager) serviceManager.lookup(LockContentManager.ROLE);
081        _contentWorkflowHelper = (ContentWorkflowHelper) serviceManager.lookup(ContentWorkflowHelper.ROLE);
082        _contentHelper = (ContentHelper) serviceManager.lookup(ContentHelper.ROLE);
083    }
084    
085    @SuppressWarnings("unchecked")
086    @Override
087    public void generate() throws IOException, SAXException, ProcessingException
088    {
089        Map<String, Object> jsParameters = (Map<String, Object>) objectModel.get(ObjectModelHelper.PARENT_CONTEXT);
090        List<String> ids = null;
091        Object idParam = jsParameters.get("id");
092        if (idParam instanceof String)
093        {
094            ids = new ArrayList<>();
095            ids.add((String) idParam);
096        }
097        else
098        {
099            ids = (List<String>) idParam;
100        }
101        
102        contentHandler.startDocument();
103        XMLUtils.startElement(contentHandler, "contents");
104        
105        for (String contentID : ids)
106        {
107            AttributesImpl attrs = new AttributesImpl();
108            
109            try
110            {
111                Content content = _resolver.resolveById(contentID);
112                
113                attrs.addCDATAAttribute("id", content.getId());
114                attrs.addCDATAAttribute("title", _contentHelper.getTitle(content));
115                attrs.addCDATAAttribute("name", content.getName());
116                attrs.addCDATAAttribute("path", content.getPath());
117                attrs.addCDATAAttribute("type", StringUtils.join(content.getTypes(), ','));
118                if (content.getLanguage() != null)
119                {
120                    attrs.addCDATAAttribute("lang", content.getLanguage());
121                }
122                attrs.addCDATAAttribute("creator", content.getCreator().getLogin());
123                attrs.addCDATAAttribute("lastContributor", content.getLastContributor().getLogin());
124                attrs.addCDATAAttribute("creationDate", DateUtils.zonedDateTimeToString(content.getCreationDate()));
125                attrs.addCDATAAttribute("lastModified", DateUtils.zonedDateTimeToString(content.getLastModified()));
126                
127                if (content instanceof WorkflowAwareContent)
128                {
129                    WorkflowAwareContent waContent = (WorkflowAwareContent) content;
130                    AmetysObjectWorkflow workflow = _workflowProvider.getAmetysObjectWorkflow(waContent);
131                    
132                    attrs.addCDATAAttribute("workflowName", workflow.getWorkflowName(waContent.getWorkflowId()));
133                    attrs.addCDATAAttribute("workflowStep", this.__joinSteps(workflow.getCurrentSteps(waContent.getWorkflowId())));
134                    
135                    int[] availableActions = _contentWorkflowHelper.getAvailableActions(waContent);
136                    String workflowAvailableAction = StringUtils.join(ArrayUtils.toObject(availableActions), ", ");
137                    attrs.addCDATAAttribute("workflowAvailableActions", workflowAvailableAction);
138                }
139                
140                if (content instanceof ModifiableContent)
141                {
142                    attrs.addCDATAAttribute("isModifiable", "true");
143                }
144                
145                if (content instanceof LockAwareAmetysObject)
146                {
147                    LockAwareAmetysObject lockAwareContent = (LockAwareAmetysObject) content;
148                    if (lockAwareContent.isLocked())
149                    {
150                        attrs.addCDATAAttribute("locked", String.valueOf(lockAwareContent.isLocked()));
151                        attrs.addCDATAAttribute("canUnlock", String.valueOf(_lockManager.canUnlock(lockAwareContent)));
152                    }
153                }
154                
155                saxAdditionalAtttributes (content, attrs);
156                
157                XMLUtils.startElement(contentHandler, "content", attrs);
158                
159                saxUserRights(content);
160                saxAdditionalInformation(content);
161                XMLUtils.endElement(contentHandler, "content");
162            }
163            catch (UnknownAmetysObjectException e)
164            {
165                getLogger().warn("Content of id '" + contentID + "' does not exist.", e);
166                
167                attrs.addCDATAAttribute("id", contentID);
168                XMLUtils.createElement(contentHandler, "content-not-found", attrs);
169            }
170            
171        }
172        
173        XMLUtils.endElement(contentHandler, "contents");
174        contentHandler.endDocument();
175    }
176
177    private String __joinSteps(List<Step> steps)
178    {
179        StringBuffer a = new StringBuffer();
180        
181        for (Step s : steps)
182        {
183            if (a.length() > 0)
184            {
185                a.append(", ");
186            }
187            a.append(s.getStepId());
188        }
189        
190        return a.toString();
191    }
192    
193    
194    /**
195     * SAX the user rights on content
196     * @param content The content to check rights
197     * @throws SAXException if an error occurred while SAXing
198     */
199    protected void saxUserRights (Content content) throws SAXException
200    {
201        UserIdentity user = _userProvider.getUser();
202        Set<String> rights = _rightManager.getUserRights(user, content);
203        
204        XMLUtils.startElement(contentHandler, "user-rights");
205        
206        for (String rightID : rights)
207        {
208            AttributesImpl rightAttr = new AttributesImpl();
209            rightAttr.addCDATAAttribute("id", rightID);
210            XMLUtils.createElement(contentHandler, "right", rightAttr);
211        }
212        XMLUtils.endElement(contentHandler, "user-rights");
213    }
214    
215    /**
216     * SAX the additional attributes
217     * @param content The content
218     * @param attrs The attributes
219     * @throws SAXException if an error occurred while SAXing
220     */
221    protected void saxAdditionalAtttributes (Content content, AttributesImpl attrs) throws SAXException
222    {
223        // Nothing
224    }
225    
226    /**
227     * SAX additional information on content
228     * @param content The content
229     * @throws SAXException if an error occurred while SAXing
230     */
231    protected void saxAdditionalInformation (Content content) throws SAXException
232    {
233        // Nothing
234    }
235}