001/*
002 *  Copyright 2016 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.forms.data;
017
018import java.util.ArrayList;
019import java.util.Date;
020import java.util.HashMap;
021import java.util.List;
022import java.util.Map;
023
024import javax.jcr.Node;
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.ProcessingException;
030import org.apache.cocoon.acting.ServiceableAction;
031import org.apache.cocoon.environment.ObjectModelHelper;
032import org.apache.cocoon.environment.Redirector;
033import org.apache.cocoon.environment.Request;
034import org.apache.cocoon.environment.SourceResolver;
035import org.apache.commons.lang.StringUtils;
036
037import org.ametys.cms.content.ContentHelper;
038import org.ametys.cms.repository.Content;
039import org.ametys.cms.transformation.xslt.URIDecoder;
040import org.ametys.core.cocoon.JSonReader;
041import org.ametys.plugins.forms.Form;
042import org.ametys.plugins.forms.FormsException;
043import org.ametys.plugins.forms.jcr.FormPropertiesManager;
044import org.ametys.plugins.forms.table.FormTableManager;
045import org.ametys.plugins.repository.AmetysObjectResolver;
046import org.ametys.runtime.parameter.ParameterHelper;
047
048/**
049 * This generator is used in order to retrieve information on the forms 
050 * of a given site in a given language
051 */
052public class GetFormsListAction extends ServiceableAction
053{
054    /** Component gathering methods to retrieve forms */
055    private FormPropertiesManager _formPropertiesManager;
056    
057    /** The form data manager */
058    private FormTableManager _formTableManager;
059    
060    /** The Ametys object resolver */
061    private AmetysObjectResolver _resolver;
062    
063    private ContentHelper _contentHelper;
064    
065    @Override
066    public void service(ServiceManager serviceManager) throws ServiceException
067    {
068        _formPropertiesManager = (FormPropertiesManager) serviceManager.lookup(FormPropertiesManager.ROLE);
069        _formTableManager = (FormTableManager) serviceManager.lookup(FormTableManager.ROLE);
070        _resolver = (AmetysObjectResolver) serviceManager.lookup(AmetysObjectResolver.ROLE);
071        _contentHelper = (ContentHelper) serviceManager.lookup(ContentHelper.ROLE);
072    }
073    
074    @Override
075    public Map act(Redirector redirector, SourceResolver resolver, Map objectModel, String source, Parameters parameters) throws Exception
076    {
077        @SuppressWarnings("unchecked")
078        Map<String, Object> jsParameters = (Map<String, Object>) objectModel.get(ObjectModelHelper.PARENT_CONTEXT);
079        
080        String siteName = (String) jsParameters.get("siteName");
081        String language = (String) jsParameters.get("lang");
082        
083        
084        if (StringUtils.isEmpty(siteName) || StringUtils.isEmpty(language))
085        {
086            throw new ProcessingException("The site name and language must be provided.");
087        }
088        
089        Map<String, Object> result = new HashMap<>();
090        
091        List<Map<String, Object>> formsList = new ArrayList<> ();
092        try
093        {
094            List<Node> contentNodes = _formPropertiesManager.getFormContentNodes(siteName, language);
095            for (Node contentNode : contentNodes)
096            {
097                Content content = _resolver.resolve(contentNode, false);
098                
099                // Get the corresponding forms
100                List<Form> forms = _formPropertiesManager.getForms(contentNode);
101                for (Form form : forms)
102                {
103                    Map<String, Object> formMap = new HashMap<> ();
104                    try
105                    {
106                        Map<String, FieldValue> columns = _formTableManager.getColumns(form);
107                        
108                        List<UserEntry> entries = _formTableManager.getSubmissions(form, columns, 0, Integer.MAX_VALUE, null);
109                        int totalSubmissions = _formTableManager.getTotalSubmissions(form.getId());
110                        Date lastSubmissionDate = _getLastSubmissionDate(entries);
111                        
112                        formMap.put("id", form.getId());
113                        formMap.put("label", URIDecoder.decode(form.getLabel()));
114                        formMap.put("contentName", content.getName());
115                        formMap.put("contentId", content.getId());
116                        formMap.put("contentTitle", _contentHelper.getTitle(content));
117                        
118                        formMap.put("answersAmount", String.valueOf(totalSubmissions));
119                        formMap.put("lastAnswer", lastSubmissionDate != null ? ParameterHelper.valueToString(lastSubmissionDate) : null);
120                        formMap.put("workflowName", StringUtils.defaultString(form.getWorkflowName(), ""));
121                        
122                        formsList.add(formMap);
123                    }
124                    catch (FormsException e)
125                    {
126                        getLogger().error("Failed to get SQL table for form '" + form.getId() + "' for content of id '" + content.getId() + "'", e);
127                    }
128                }
129            }
130            
131            result.put("forms", formsList);
132        }
133        catch (Exception e)
134        {
135            throw new ProcessingException("An error occurred while processing the forms list.", e);
136        }
137        
138        Request request = ObjectModelHelper.getRequest(objectModel);
139        request.setAttribute(JSonReader.OBJECT_TO_READ, result);
140        return EMPTY_MAP;
141    }
142    
143    /**
144     * Get the date of the most recent {@link UserEntry}
145     * @param entries the list of entries
146     * @return the date of the most recent entry
147     */
148    private Date _getLastSubmissionDate (List<UserEntry> entries)
149    {
150        Date lastSubmissionDate = null;
151        if (entries.size() > 0)
152        {
153            lastSubmissionDate = entries.get(0).getCreationDate();
154            for (UserEntry entry : entries)
155            {
156                Date creationDate = entry.getCreationDate();
157                if (lastSubmissionDate.before(creationDate))
158                {
159                    lastSubmissionDate = creationDate;
160                }
161            }
162        }
163        
164        return lastSubmissionDate;
165    }
166}