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.plugins.forms.data; 017 018import java.util.ArrayList; 019import java.util.HashMap; 020import java.util.Iterator; 021import java.util.LinkedHashMap; 022import java.util.List; 023import java.util.Map; 024import java.util.regex.Matcher; 025import java.util.regex.Pattern; 026 027import org.apache.avalon.framework.parameters.Parameters; 028import org.apache.avalon.framework.service.ServiceException; 029import org.apache.avalon.framework.service.ServiceManager; 030import org.apache.cocoon.ProcessingException; 031import org.apache.cocoon.acting.ServiceableAction; 032import org.apache.cocoon.environment.ObjectModelHelper; 033import org.apache.cocoon.environment.Redirector; 034import org.apache.cocoon.environment.Request; 035import org.apache.cocoon.environment.SourceResolver; 036 037import org.ametys.core.cocoon.JSonReader; 038import org.ametys.core.util.I18nUtils; 039import org.ametys.plugins.forms.Field; 040import org.ametys.plugins.forms.Field.FieldType; 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.plugins.workflow.store.JdbcWorkflowStore; 047import org.ametys.plugins.workflow.support.WorkflowProvider; 048import org.ametys.runtime.i18n.I18nizableText; 049import org.ametys.runtime.parameter.ParameterHelper; 050 051import com.opensymphony.workflow.Workflow; 052import com.opensymphony.workflow.loader.StepDescriptor; 053import com.opensymphony.workflow.loader.WorkflowDescriptor; 054import com.opensymphony.workflow.spi.Step; 055 056/** 057 * Get the submitted entries of a form 058 * 059 */ 060public class GetFormEntriesAction extends ServiceableAction 061{ 062 /** Pattern for options value */ 063 protected static final Pattern __OPTION_VALUE_PATTERN = Pattern.compile("^option-([0-9]+)-value$"); 064 065 /** The internationalizable text symbolizing the absence of workflow step */ 066 protected static final I18nizableText __MESSAGE_NO_STEP = new I18nizableText("plugin.forms", "PLUGINS_FORMS_UITOOL_ENTRY_WORKFLOW_NO_WORKFLOW"); 067 068 /** The form properties manager. */ 069 protected FormPropertiesManager _formPropertiesManager; 070 071 /** The form data manager. */ 072 protected FormTableManager _formTableManager; 073 074 /** The ametys object resolver. */ 075 protected AmetysObjectResolver _resolver; 076 077 /** The workflow provider */ 078 protected WorkflowProvider _workflowProvider; 079 080 /** Utility component for internationalizable text */ 081 protected I18nUtils _i18nUtils; 082 083 @Override 084 public void service(ServiceManager smanager) throws ServiceException 085 { 086 super.service(smanager); 087 _resolver = (AmetysObjectResolver) smanager.lookup(AmetysObjectResolver.ROLE); 088 _formPropertiesManager = (FormPropertiesManager) smanager.lookup(FormPropertiesManager.ROLE); 089 _formTableManager = (FormTableManager) smanager.lookup(FormTableManager.ROLE); 090 _workflowProvider = (WorkflowProvider) smanager.lookup(WorkflowProvider.ROLE); 091 _i18nUtils = (I18nUtils) smanager.lookup(I18nUtils.ROLE); 092 } 093 094 @Override 095 public Map act(Redirector redirector, SourceResolver resolver, Map objectModel, String source, Parameters parameters) throws Exception 096 { 097 @SuppressWarnings("unchecked") 098 Map<String, Object> jsParameters = (Map<String, Object>) objectModel.get(ObjectModelHelper.PARENT_CONTEXT); 099 100 String siteName = (String) jsParameters.get("siteName"); 101 String formId = (String) jsParameters.get("id"); 102 103 int start = jsParameters.containsKey("start") ? (int) jsParameters.get("start") : 0; 104 int limit = jsParameters.containsKey("limit") ? (int) jsParameters.get("limit") : Integer.MAX_VALUE; 105 106 Form form = _formPropertiesManager.getForm(siteName, formId); 107 108 if (form == null) 109 { 110 throw new ProcessingException("The form of ID '" + formId + " can't be found in the site '" + siteName + "'."); 111 } 112 113 Workflow workflow = _workflowProvider.getExternalWorkflow(JdbcWorkflowStore.ROLE); 114 Map<String, Object> result = new HashMap<>(); 115 List<Map<String, Object>> entries2json = new ArrayList<>(); 116 try 117 { 118 Map<String, FieldValue> columns = _formTableManager.getColumns(form); 119 List<UserEntry> entries = _formTableManager.getSubmissions(form, columns, start, limit, null); 120 int totalSubmissions = _formTableManager.getTotalSubmissions(form.getId()); 121 122 result.put("id", form.getId()); 123 result.put("label", form.getLabel()); 124 result.put("total", totalSubmissions); 125 126 for (UserEntry entry : entries) 127 { 128 entries2json.add(_entry2json(entry, workflow)); 129 } 130 } 131 catch (FormsException e) 132 { 133 getLogger().error("Failed to get SQL table for form '" + form.getId() + "' for content of id.", e); 134 } 135 136 result.put("entries", entries2json); 137 138 Request request = ObjectModelHelper.getRequest(objectModel); 139 request.setAttribute(JSonReader.OBJECT_TO_READ, result); 140 return EMPTY_MAP; 141 } 142 143 private Map<String, Object> _entry2json(UserEntry entry, Workflow workflow) 144 { 145 Map<String, Object> entryAsMap = new HashMap<>(); 146 147 entryAsMap.put("id", entry.getId()); 148 entryAsMap.put("submission-date", ParameterHelper.valueToString(entry.getCreationDate())); 149 150 if (entry.getWorkflowId() != null) 151 { 152 entryAsMap.put("workflowStep", _workflow2json (entry, workflow)); 153 } 154 155 for (FieldValue fdValue : entry.getValues()) 156 { 157 Object rawValue = fdValue.getValue(); 158 if (rawValue != null) 159 { 160 entryAsMap.put(fdValue.getColumnName() + "_raw", rawValue); 161 entryAsMap.put(fdValue.getColumnName(), _getReadableValue(fdValue.getField(), rawValue)); 162 } 163 } 164 165 return entryAsMap; 166 } 167 168 private Map<String, Object> _workflow2json (UserEntry entry, Workflow workflow) 169 { 170 Map<String, Object> workflowInfos = new LinkedHashMap<>(); 171 172 int currentStepId = 0; 173 174 long workflowId = entry.getWorkflowId(); 175 Iterator<Step> currentSteps = workflow.getCurrentSteps(workflowId).iterator(); 176 177 while (currentSteps.hasNext()) 178 { 179 Step step = currentSteps.next(); 180 currentStepId = step.getStepId(); 181 } 182 183 String workflowName = workflow.getWorkflowName(workflowId); 184 WorkflowDescriptor workflowDescriptor = workflow.getWorkflowDescriptor(workflowName); 185 StepDescriptor stepDescriptor = workflowDescriptor.getStep(currentStepId); 186 187 if (stepDescriptor != null) 188 { 189 I18nizableText workflowStepName = new I18nizableText("application", stepDescriptor.getName()); 190 191 workflowInfos.put("stepId", currentStepId); 192 workflowInfos.put("name", workflowStepName); 193 194 String[] icons = new String[] {"small", "medium", "large"}; 195 for (String icon : icons) 196 { 197 if ("application".equals(workflowStepName.getCatalogue())) 198 { 199 workflowInfos.put(icon + "Icon", "/plugins/cms/resources_workflow/" + workflowStepName.getKey() + "-" + icon + ".png"); 200 } 201 else 202 { 203 String pluginName = workflowStepName.getCatalogue().substring("plugin.".length()); 204 workflowInfos.put(icon + "Icon", "/plugins/" + pluginName + "/resources/img/workflow/" + workflowStepName.getKey() + "-" + icon + ".png"); 205 } 206 } 207 } 208 209 return workflowInfos; 210 } 211 212 /** 213 * Get label to display for field 214 * @param field The field 215 * @param value The value 216 * @return The value to display 217 */ 218 protected String _getReadableValue (Field field, Object value) 219 { 220 if (field.getType().equals(FieldType.SELECT) || field.getType().equals(FieldType.RADIO)) 221 { 222 Map<String, String> properties = field.getProperties(); 223 for (String key : properties.keySet()) 224 { 225 Matcher matcher = __OPTION_VALUE_PATTERN.matcher(key); 226 if (matcher.matches()) 227 { 228 if (value.equals(properties.get(key))) 229 { 230 String index = matcher.group(1); 231 if (properties.containsKey("option-" + index + "-label")) 232 { 233 return properties.get("option-" + index + "-label"); 234 } 235 } 236 } 237 } 238 } 239 240 return ParameterHelper.valueToString(value); 241 } 242 243}