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.plugins.survey.generators; 017 018import java.io.IOException; 019import java.util.Arrays; 020import java.util.Collections; 021import java.util.HashMap; 022import java.util.HashSet; 023import java.util.Map; 024import java.util.Set; 025 026import org.apache.avalon.framework.parameters.ParameterException; 027import org.apache.avalon.framework.service.ServiceException; 028import org.apache.avalon.framework.service.ServiceManager; 029import org.apache.cocoon.ProcessingException; 030import org.apache.cocoon.generation.ServiceableGenerator; 031import org.apache.cocoon.xml.AttributesImpl; 032import org.apache.cocoon.xml.XMLUtils; 033import org.apache.commons.lang.StringUtils; 034import org.joda.time.DateTime; 035import org.joda.time.format.ISODateTimeFormat; 036import org.xml.sax.SAXException; 037 038import org.ametys.core.user.UserIdentity; 039import org.ametys.plugins.repository.AmetysObjectResolver; 040import org.ametys.plugins.survey.data.SurveyAnswer; 041import org.ametys.plugins.survey.data.SurveyAnswerDao; 042import org.ametys.plugins.survey.data.SurveySession; 043import org.ametys.plugins.survey.repository.Survey; 044import org.ametys.plugins.survey.repository.SurveyQuestion; 045 046/** 047 * Generates a specific survey user session from its ID. 048 */ 049public class SurveySessionGenerator extends ServiceableGenerator 050{ 051 052 /** The ametys object resolver. */ 053 protected AmetysObjectResolver _resolver; 054 055 /** The survey data DAO. */ 056 protected SurveyAnswerDao _surveyDao; 057 058 @Override 059 public void service(ServiceManager serviceManager) throws ServiceException 060 { 061 super.service(serviceManager); 062 _resolver = (AmetysObjectResolver) serviceManager.lookup(AmetysObjectResolver.ROLE); 063 _surveyDao = (SurveyAnswerDao) serviceManager.lookup(SurveyAnswerDao.ROLE); 064 } 065 066 @Override 067 public void generate() throws IOException, SAXException, ProcessingException 068 { 069// Request request = ObjectModelHelper.getRequest(objectModel); 070 071 // Get the session ID. 072 int sessionId; 073 try 074 { 075 sessionId = parameters.getParameterAsInteger("id"); 076 } 077 catch (ParameterException e) 078 { 079 throw new ProcessingException("Session ID is mandatory.", e); 080 } 081 082 // Retrieve the corresponding session from the database. 083 SurveySession surveySession = _surveyDao.getSessionWithAnswers(sessionId); 084 085 // Resolve the corresponding survey. 086 Survey survey = _resolver.resolveById(surveySession.getSurveyId()); 087 088 contentHandler.startDocument(); 089 090 // Generate the session and its answers. 091 saxSession(surveySession, survey, true); 092 093 contentHandler.endDocument(); 094 } 095 096 /** 097 * Generate the data of a survey user session. 098 * @param surveySession the survey session. 099 * @param survey the survey. 100 * @param withAnswers true to generate answers along, false otherwise. 101 * @throws SAXException if an error occurs while saxing the session 102 */ 103 protected void saxSession(SurveySession surveySession, Survey survey, boolean withAnswers) throws SAXException 104 { 105 DateTime submittedAt = new DateTime(surveySession.getSubmittedAt().getTime()); 106 107 AttributesImpl attrs = new AttributesImpl(); 108 attrs.addCDATAAttribute("id", Integer.toString(surveySession.getId())); 109 attrs.addCDATAAttribute("submittedAt", ISODateTimeFormat.dateTime().print(submittedAt)); 110 UserIdentity user = surveySession.getUser(); 111 if (user != null) 112 { 113 attrs.addCDATAAttribute("user", UserIdentity.userIdentityToString(user)); 114 } 115 116 XMLUtils.startElement(contentHandler, "session", attrs); 117 118 if (withAnswers) 119 { 120 saxAnswers(surveySession, survey); 121 } 122 123 XMLUtils.endElement(contentHandler, "session"); 124 } 125 126 /** 127 * Generate the answers of a given session. 128 * @param surveySession the survey session. 129 * @param survey the survey. 130 * @throws SAXException if an error occurs while saxing the answers 131 */ 132 protected void saxAnswers(SurveySession surveySession, Survey survey) throws SAXException 133 { 134 AttributesImpl attrs = new AttributesImpl(); 135 136 Map<String, SurveyAnswer> answerMap = getAnswerMap(surveySession); 137 138 for (SurveyQuestion question : survey.getQuestions()) 139 { 140 SurveyAnswer answer = answerMap.get(question.getName()); 141 142 attrs.clear(); 143 attrs.addCDATAAttribute("name", question.getName()); 144 attrs.addCDATAAttribute("title", question.getTitle()); 145 attrs.addCDATAAttribute("type", question.getType().toString()); 146 attrs.addCDATAAttribute("mandatory", Boolean.toString(question.isMandatory())); 147 XMLUtils.startElement(contentHandler, "question", attrs); 148 149 if (answer != null) 150 { 151 Map<String, Set<String>> values = getValueMap(question, answer.getValue()); 152 153 for (String option : values.keySet()) 154 { 155 attrs.clear(); 156 attrs.addCDATAAttribute("name", option); 157 XMLUtils.startElement(contentHandler, "option", attrs); 158 159 for (String value : values.get(option)) 160 { 161 attrs.clear(); 162 attrs.addCDATAAttribute("value", value); 163 XMLUtils.createElement(contentHandler, "answer", attrs); 164 } 165 166 XMLUtils.endElement(contentHandler, "option"); 167 } 168 } 169 170 XMLUtils.endElement(contentHandler, "question"); 171 } 172 } 173 174 /** 175 * Get the answers of a survey session as a Map, indexed by question ID. 176 * @param surveySession the survey session. 177 * @return the answers as a Map, indexed by question ID. 178 */ 179 protected Map<String, SurveyAnswer> getAnswerMap(SurveySession surveySession) 180 { 181 Map<String, SurveyAnswer> answerMap = new HashMap<>(); 182 183 for (SurveyAnswer answer : surveySession.getAnswers()) 184 { 185 answerMap.put(answer.getQuestionId(), answer); 186 } 187 188 return answerMap; 189 } 190 191 /** 192 * Get the user-input value as a Map from the database value, which is a single serialized string. 193 * @param question the question. 194 * @param value the value from the database. 195 * @return the value as a Map. 196 */ 197 protected Map<String, Set<String>> getValueMap(SurveyQuestion question, String value) 198 { 199 Map<String, Set<String>> values = new HashMap<>(); 200 201 if (value != null) 202 { 203 switch (question.getType()) 204 { 205 case SINGLE_MATRIX: 206 case MULTIPLE_MATRIX: 207 String[] entries = StringUtils.split(value, ';'); 208 for (String entry : entries) 209 { 210 String[] keyValue = StringUtils.split(entry, ':'); 211 if (keyValue.length == 2 && StringUtils.isNotEmpty(keyValue[0])) 212 { 213 Set<String> valueSet = new HashSet<>(Arrays.asList(StringUtils.split(keyValue[1], ','))); 214 215 values.put(keyValue[0], valueSet); 216 } 217 } 218 break; 219 case SINGLE_CHOICE: 220 case MULTIPLE_CHOICE: 221 Set<String> valueSet = new HashSet<>(Arrays.asList(StringUtils.split(value, ','))); 222 values.put("values", valueSet); 223 break; 224 case FREE_TEXT: 225 case MULTILINE_FREE_TEXT: 226 default: 227 values.put("values", Collections.singleton(value)); 228 break; 229 } 230 } 231 232 return values; 233 } 234 235}