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.survey.dao; 017 018import java.util.ArrayList; 019import java.util.HashMap; 020import java.util.LinkedHashMap; 021import java.util.List; 022import java.util.Map; 023 024import org.apache.commons.lang.StringUtils; 025 026import org.ametys.cms.FilterNameHelper; 027import org.ametys.core.observation.Event; 028import org.ametys.core.ui.Callable; 029import org.ametys.plugins.repository.UnknownAmetysObjectException; 030import org.ametys.plugins.survey.SurveyEvents; 031import org.ametys.plugins.survey.repository.Survey; 032import org.ametys.plugins.survey.repository.SurveyPage; 033import org.ametys.plugins.survey.repository.SurveyQuestion; 034import org.ametys.plugins.survey.repository.SurveyQuestion.QuestionType; 035import org.ametys.plugins.survey.repository.SurveyRule; 036import org.ametys.plugins.survey.repository.SurveyRule.RuleType; 037 038/** 039 * DAO for manipulating survey questions. 040 * 041 */ 042public class QuestionDAO extends AbstractDAO 043{ 044 /** The Avalon role */ 045 public static final String ROLE = QuestionDAO.class.getName(); 046 047 /** 048 * Gets properties of a survey question 049 * @param id The id of the survey question 050 * @return The properties 051 */ 052 @Callable 053 public Map<String, Object> getQuestion (String id) 054 { 055 SurveyQuestion question = _resolver.resolveById(id); 056 057 return getQuestion(question); 058 } 059 060 /** 061 * Gets properties of a survey question 062 * @param question The survey question 063 * @return The properties 064 */ 065 public Map<String, Object> getQuestion (SurveyQuestion question) 066 { 067 Map<String, Object> properties = new HashMap<>(); 068 069 properties.put("id", question.getId()); 070 properties.put("type", question.getType()); 071 properties.put("label", question.getLabel()); 072 properties.put("title", question.getTitle()); 073 properties.put("regexp", question.getRegExpType()); 074 properties.put("mandatory", String.valueOf(question.isMandatory())); 075 properties.put("validated", String.valueOf(question.getSurvey().isValidated())); 076 077 Map<String, String> columns = question.getColumns(); 078 if (columns.size() > 0) 079 { 080 properties.put("columns", columns); 081 } 082 083 Map<String, String> options = question.getOptions(); 084 if (options.size() > 0) 085 { 086 properties.put("otherOption", String.valueOf(question.hasOtherOption())); 087 properties.put("options", options); 088 } 089 090 properties.putAll(getPictureInfo(question)); 091 092 return properties; 093 } 094 095 /** 096 * Creates a survey question. 097 * @param values The question's values 098 * @return The id of the created survey question, the id of the page and the id of the survey 099 */ 100 @Callable 101 public Map<String, String> createQuestion (Map<String, Object> values) 102 { 103 Map<String, String> result = new HashMap<>(); 104 105 String pageId = StringUtils.defaultString((String) values.get("pageId")); 106 SurveyPage page = _resolver.resolveById(pageId); 107 108 String label = StringUtils.defaultString((String) values.get("label")); 109 String originalName = FilterNameHelper.filterName(label); 110 111 // Find unique name 112 String uniqueName = page.getSurvey().findUniqueQuestionName(originalName); 113 114 SurveyQuestion question = page.createChild(uniqueName, "ametys:survey-question"); 115 116 _setValues(question, values); 117 118 page.saveChanges(); 119 120 Map<String, Object> eventParams = new HashMap<>(); 121 eventParams.put("survey", page.getSurvey()); 122 _observationManager.notify(new Event(SurveyEvents.SURVEY_MODIFIED, _getCurrentUser(), eventParams)); 123 124 result.put("id", question.getId()); 125 result.put("pageId", page.getId()); 126 result.put("surveyId", question.getSurvey().getId()); 127 result.put("type", question.getType().toString()); 128 129 return result; 130 } 131 132 /** 133 * Edits a survey question. 134 * @param values The question's values 135 * @return The id of the edited survey question, the id of the page and the id of the survey 136 */ 137 @Callable 138 public Map<String, String> editQuestion (Map<String, Object> values) 139 { 140 Map<String, String> result = new HashMap<>(); 141 142 String id = StringUtils.defaultString((String) values.get("id")); 143 SurveyQuestion question = _resolver.resolveById(id); 144 145 _setValues(question, values); 146 147 question.saveChanges(); 148 149 Map<String, Object> eventParams = new HashMap<>(); 150 eventParams.put("survey", question.getSurvey()); 151 _observationManager.notify(new Event(SurveyEvents.SURVEY_MODIFIED, _getCurrentUser(), eventParams)); 152 153 result.put("id", question.getId()); 154 result.put("pageId", question.getParent().getId()); 155 result.put("surveyId", question.getSurvey().getId()); 156 result.put("type", question.getType().toString()); 157 158 return result; 159 } 160 161 private void _setValues (SurveyQuestion question, Map<String, Object> values) 162 { 163 question.setTitle(StringUtils.defaultString((String) values.get("title"))); 164 question.setLabel(StringUtils.defaultString((String) values.get("label"))); 165 question.setMandatory("true".equals(values.get("mandatory"))); 166 167 String qType = StringUtils.defaultString((String) values.get("type")); 168 question.setType(QuestionType.valueOf(qType)); 169 question.setRegExpType(StringUtils.defaultString((String) values.get("regexp"))); 170 171 question.setPictureAlternative(StringUtils.defaultString((String) values.get("picture-alternative"))); 172 setPicture(question, StringUtils.defaultString((String) values.get("picture"))); 173 174 boolean hasOtherOption = "true".equals(values.get("otherOption")); 175 176 String options = (String) values.get("options"); 177 if (StringUtils.isNotEmpty(options)) 178 { 179 Map<String, Object> rawOpts = _jsonUtils.convertJsonToMap(options); 180 Map<String, String> opts = new LinkedHashMap<>(); 181 182 for (String optLabel : rawOpts.keySet()) 183 { 184 String optVal = (String) rawOpts.get(optLabel); 185 if (StringUtils.isEmpty(optVal)) 186 { 187 optVal = FilterNameHelper.filterName(SurveyQuestion.OPTION_NAME_PREFIX + optLabel); 188 } 189 opts.put(optVal, optLabel); 190 } 191 question.setOptions(opts); 192 question.setOtherOption(hasOtherOption); 193 } 194 195 String columns = (String) values.get("columns"); 196 if (StringUtils.isNotEmpty(columns)) 197 { 198 Map<String, Object> rawCols = _jsonUtils.convertJsonToMap(columns); 199 Map<String, String> cols = new LinkedHashMap<>(); 200 201 for (String colLabel : rawCols.keySet()) 202 { 203 String colVal = (String) rawCols.get(colLabel); 204 if (StringUtils.isEmpty(colVal)) 205 { 206 colVal = FilterNameHelper.filterName(SurveyQuestion.OPTION_NAME_PREFIX + colLabel); 207 } 208 cols.put(colVal, colLabel); 209 } 210 211 question.setColumns(cols); 212 } 213 } 214 215 /** 216 * Copies and pastes a survey question. 217 * @param pageId The id of the page, target of the copy 218 * @param questionId The id of the question to copy 219 * @return The id of the created question, the id of the page and the id of the survey 220 */ 221 @Callable 222 public Map<String, String> copyQuestion(String pageId, String questionId) 223 { 224 Map<String, String> result = new HashMap<>(); 225 226 SurveyQuestion originalQuestion = _resolver.resolveById(questionId); 227 SurveyPage parentPage = _resolver.resolveById(pageId); 228 229 Survey originalSurvey = originalQuestion.getSurvey(); 230 Survey parentSurvey = parentPage.getSurvey(); 231 232 String name = parentSurvey.findUniqueQuestionName(originalQuestion.getName()); 233 SurveyQuestion cQuestion = originalQuestion.copyTo(parentPage, name); 234 235 if (!originalSurvey.getId().equals(parentSurvey.getId())) 236 { 237 // Update rules references after copy 238 updateReferencesAfterCopy (originalSurvey, parentSurvey, cQuestion); 239 } 240 241 parentPage.saveChanges(); 242 243 Map<String, Object> eventParams = new HashMap<>(); 244 eventParams.put("survey", parentSurvey); 245 _observationManager.notify(new Event(SurveyEvents.SURVEY_MODIFIED, _getCurrentUser(), eventParams)); 246 247 result.put("id", cQuestion.getId()); 248 result.put("pageId", parentPage.getId()); 249 result.put("surveyId", parentSurvey.getId()); 250 result.put("type", cQuestion.getType().toString()); 251 252 return result; 253 } 254 255 /** 256 * Deletes a survey question. 257 * @param id The id of the survey question to delete 258 * @return The id of the deleted survey question, the id of the page and the id of the survey 259 */ 260 @Callable 261 public Map<String, String> deleteQuestion (String id) 262 { 263 Map<String, String> result = new HashMap<>(); 264 265 SurveyQuestion question = _resolver.resolveById(id); 266 String type = question.getType().toString(); 267 268 SurveyPage page = question.getParent(); 269 question.remove(); 270 271 page.saveChanges(); 272 273 Map<String, Object> eventParams = new HashMap<>(); 274 eventParams.put("survey", page.getSurvey()); 275 _observationManager.notify(new Event(SurveyEvents.SURVEY_MODIFIED, _getCurrentUser(), eventParams)); 276 277 result.put("id", id); 278 result.put("pageId", page.getId()); 279 result.put("surveyId", page.getSurvey().getId()); 280 result.put("type", type); 281 282 return result; 283 } 284 285 /** 286 * Adds a new rule to a question. 287 * @param id _resolver.resolveById(id); 288 * @param option The option 289 * @param rule The rule type 290 * @param page The page to jump or skip 291 * @return An empty map, or an error 292 */ 293 @Callable 294 public Map<String, Object> addRule (String id, String option, String rule, String page) 295 { 296 Map<String, Object> result = new HashMap<>(); 297 298 SurveyQuestion question = _resolver.resolveById(id); 299 // Check if exists 300 if (question.hasRule(option)) 301 { 302 result.put("error", "already-exists"); 303 return result; 304 } 305 306 question.addRules(option, RuleType.valueOf(rule), page); 307 question.saveChanges(); 308 309 Map<String, Object> eventParams = new HashMap<>(); 310 eventParams.put("survey", question.getSurvey()); 311 _observationManager.notify(new Event(SurveyEvents.SURVEY_MODIFIED, _getCurrentUser(), eventParams)); 312 313 return result; 314 } 315 316 /** 317 * Deletes a rule to a question. 318 * @param id _resolver.resolveById(id); 319 * @param option The option to delete 320 * @return An empty map 321 */ 322 @Callable 323 public Map<String, Object> deleteRule (String id, String option) 324 { 325 SurveyQuestion question = _resolver.resolveById(id); 326 327 question.deleteRule(option); 328 question.saveChanges(); 329 330 Map<String, Object> eventParams = new HashMap<>(); 331 eventParams.put("survey", question.getSurvey()); 332 _observationManager.notify(new Event(SurveyEvents.SURVEY_MODIFIED, _getCurrentUser(), eventParams)); 333 334 return new HashMap<>(); 335 } 336 337 /** 338 * Gets the rules for a survey question. 339 * @param id The id of the survey question. 340 * @param number The question number 341 * @return The rules 342 */ 343 @Callable 344 public Map<String, Object> getRules (String id, int number) 345 { 346 Map<String, Object> result = new HashMap<>(); 347 348 SurveyQuestion question = _resolver.resolveById(id); 349 Map<String, String> options = question.getOptions(); 350 351 result.put("id", question.getId()); 352 result.put("number", String.valueOf(number)); 353 result.put("title", question.getTitle()); 354 355 List<Object> rules = new ArrayList<>(); 356 for (SurveyRule rule : question.getRules()) 357 { 358 Map<String, Object> resultRule = new HashMap<>(); 359 String option = rule.getOption(); 360 resultRule.put("option", option); 361 resultRule.put("optionLabel", options.get(option)); 362 resultRule.put("type", rule.getType().name()); 363 String page = rule.getPage(); 364 if (page != null) 365 { 366 try 367 { 368 SurveyPage pageAO = _resolver.resolveById(page); 369 resultRule.put("page", page); 370 resultRule.put("pageName", pageAO.getLabel()); 371 } 372 catch (UnknownAmetysObjectException e) 373 { 374 // Page does not exist anymore 375 } 376 } 377 378 rules.add(resultRule); 379 } 380 381 result.put("rules", rules); 382 383 return result; 384 } 385 386}