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.List; 020import java.util.Map; 021 022import javax.jcr.RepositoryException; 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.environment.Request; 029import org.apache.cocoon.generation.ServiceableGenerator; 030import org.apache.cocoon.xml.AttributesImpl; 031import org.apache.cocoon.xml.XMLUtils; 032import org.apache.commons.lang.StringUtils; 033import org.xml.sax.SAXException; 034 035import org.ametys.plugins.explorer.resources.Resource; 036import org.ametys.plugins.repository.AmetysObject; 037import org.ametys.plugins.repository.AmetysObjectIterable; 038import org.ametys.plugins.repository.AmetysObjectResolver; 039import org.ametys.plugins.repository.ModifiableTraversableAmetysObject; 040import org.ametys.plugins.repository.UnknownAmetysObjectException; 041import org.ametys.plugins.repository.jcr.JCRAmetysObject; 042import org.ametys.plugins.repository.metadata.BinaryMetadata; 043import org.ametys.plugins.survey.dao.SurveyDAO; 044import org.ametys.plugins.survey.repository.AbstractSurveyElement; 045import org.ametys.plugins.survey.repository.Survey; 046import org.ametys.plugins.survey.repository.SurveyPage; 047import org.ametys.plugins.survey.repository.SurveyQuestion; 048import org.ametys.plugins.survey.repository.SurveyRule; 049import org.ametys.plugins.survey.repository.SurveyRule.RuleType; 050import org.ametys.web.repository.site.SiteManager; 051 052/** 053 * SAX surveys 054 * 055 */ 056public class SurveysGenerator extends ServiceableGenerator 057{ 058 /** The Ametys object resolver */ 059 protected AmetysObjectResolver _resolver; 060 /** The site manager */ 061 protected SiteManager _siteManager; 062 /** The DAO for surveys */ 063 protected SurveyDAO _surveyDAO; 064 065 @Override 066 public void service(ServiceManager serviceManager) throws ServiceException 067 { 068 super.service(serviceManager); 069 _resolver = (AmetysObjectResolver) serviceManager.lookup(AmetysObjectResolver.ROLE); 070 _siteManager = (SiteManager) serviceManager.lookup(SiteManager.ROLE); 071 _surveyDAO = (SurveyDAO) serviceManager.lookup(SurveyDAO.ROLE); 072 } 073 074 @Override 075 public void generate() throws IOException, SAXException, ProcessingException 076 { 077 Request request = ObjectModelHelper.getRequest(objectModel); 078 079 String siteName = request.getParameter("siteName"); 080 String lang = request.getParameter("lang"); 081 String id = request.getParameter("id"); 082 boolean saxChildren = parameters.getParameterAsBoolean("saxChildren", true); 083 084 contentHandler.startDocument(); 085 086 try 087 { 088 if (StringUtils.isEmpty(id) || id.equals("survey-root-node")) 089 { 090 XMLUtils.startElement(contentHandler, "surveys"); 091 092 ModifiableTraversableAmetysObject rootNode = getSurveyRootNode(siteName, lang); 093 094 AmetysObjectIterable<Survey> surveys = rootNode.getChildren(); 095 for (Survey survey : surveys) 096 { 097 toSAX(survey, false); 098 } 099 100 XMLUtils.endElement(contentHandler, "surveys"); 101 } 102 else 103 { 104 AmetysObject ao = _resolver.resolveById(id); 105 if (ao instanceof Survey) 106 { 107 toSAX((Survey) ao, saxChildren); 108 } 109 else if (ao instanceof SurveyPage) 110 { 111 toSAX((SurveyPage) ao, saxChildren, false); 112 } 113 else if (ao instanceof SurveyQuestion) 114 { 115 toSAX((SurveyQuestion) ao); 116 } 117 } 118 } 119 catch (RepositoryException e) 120 { 121 throw new ProcessingException("Unable to get surveys", e); 122 } 123 124 contentHandler.endDocument(); 125 126 } 127 128 /** 129 * SAX a survey 130 * @param survey the survey to SAX 131 * @param saxChildren true to SAX children 132 * @throws SAXException if error occurs while SAXing 133 */ 134 protected void toSAX (Survey survey, boolean saxChildren) throws SAXException 135 { 136 AttributesImpl attrs = new AttributesImpl(); 137 attrs.addCDATAAttribute("id", survey.getId()); 138 attrs.addCDATAAttribute("name", survey.getName()); 139 attrs.addCDATAAttribute("private", String.valueOf(_surveyDAO.isPrivate(survey))); 140 attrs.addCDATAAttribute("validated", String.valueOf(survey.isValidated())); 141 142 XMLUtils.startElement(contentHandler, "survey", attrs); 143 XMLUtils.createElement(contentHandler, "title", survey.getTitle()); 144 XMLUtils.createElement(contentHandler, "label", survey.getLabel()); 145 146 String description = survey.getDescription(); 147 if (description != null) 148 { 149 XMLUtils.createElement(contentHandler, "description", description); 150 } 151 152 String endingMessage = survey.getEndingMessage(); 153 if (endingMessage != null) 154 { 155 XMLUtils.createElement(contentHandler, "endingMessage", endingMessage); 156 } 157 158 toSAXPicture(survey); 159 160 if (saxChildren) 161 { 162 AmetysObjectIterable<SurveyPage> pages = survey.getChildren(); 163 for (SurveyPage page : pages) 164 { 165 toSAX(page, false, false); 166 } 167 } 168 169 XMLUtils.endElement(contentHandler, "survey"); 170 } 171 172 /** 173 * SAX a survey page 174 * @param page the page to SAX 175 * @param saxChildren true to SAX children 176 * @param saxBranches true to SAX branch logic 177 * @throws SAXException if error occurs while SAXing 178 */ 179 protected void toSAX (SurveyPage page, boolean saxChildren, boolean saxBranches) throws SAXException 180 { 181 AttributesImpl attrs = new AttributesImpl(); 182 attrs.addCDATAAttribute("id", page.getId()); 183 attrs.addCDATAAttribute("name", page.getName()); 184 185 XMLUtils.startElement(contentHandler, "page", attrs); 186 XMLUtils.createElement(contentHandler, "title", page.getTitle()); 187 XMLUtils.createElement(contentHandler, "label", page.getLabel()); 188 XMLUtils.createElement(contentHandler, "description", page.getDescription()); 189 190 toSAXPicture(page); 191 192 if (saxChildren) 193 { 194 AmetysObjectIterable<SurveyQuestion> questions = page.getChildren(); 195 for (SurveyQuestion question : questions) 196 { 197 toSAX(question); 198 } 199 } 200 201 if (saxBranches) 202 { 203 saxBranches(page); 204 } 205 206 XMLUtils.endElement(contentHandler, "page"); 207 } 208 209 /** 210 * SAX branch logic 211 * @param page the page 212 * @throws SAXException if error occurs while SAXing 213 */ 214 protected void saxBranches (SurveyPage page) throws SAXException 215 { 216 XMLUtils.startElement(contentHandler, "branches"); 217 218 AmetysObjectIterable<SurveyQuestion> questions = page.getChildren(); 219 for (SurveyQuestion question : questions) 220 { 221 List<SurveyRule> rules = question.getRules(); 222 223 for (SurveyRule rule : rules) 224 { 225 AttributesImpl attr = new AttributesImpl(); 226 attr.addCDATAAttribute("id", question.getId()); 227 attr.addCDATAAttribute("name", question.getName()); 228 attr.addCDATAAttribute("value", rule.getOption()); 229 RuleType type = rule.getType(); 230 attr.addCDATAAttribute("type", type.name()); 231 if (type == RuleType.JUMP) 232 { 233 attr.addCDATAAttribute("page", rule.getPage()); 234 } 235 XMLUtils.createElement(contentHandler, "rule", attr); 236 } 237 } 238 239 SurveyRule rule = page.getRule(); 240 if (rule != null) 241 { 242 AttributesImpl attr = new AttributesImpl(); 243 RuleType type = rule.getType(); 244 attr.addCDATAAttribute("type", type.name()); 245 if (type == RuleType.JUMP) 246 { 247 attr.addCDATAAttribute("page", rule.getPage()); 248 } 249 XMLUtils.createElement(contentHandler, "page-rule", attr); 250 } 251 252 XMLUtils.endElement(contentHandler, "branches"); 253 } 254 255 /** 256 * SAX a survey question 257 * @param question the question to SAX 258 * @throws SAXException if error occurs while SAXing 259 */ 260 protected void toSAX (SurveyQuestion question) throws SAXException 261 { 262 AttributesImpl attrs = new AttributesImpl(); 263 attrs.addCDATAAttribute("id", question.getId()); 264 attrs.addCDATAAttribute("name", question.getName()); 265 attrs.addCDATAAttribute("type", question.getType().name()); 266 attrs.addCDATAAttribute("mandatory", String.valueOf(question.isMandatory())); 267 attrs.addCDATAAttribute("modifiable", String.valueOf(!question.getSurvey().isValidated())); 268 269 XMLUtils.startElement(contentHandler, "question", attrs); 270 XMLUtils.createElement(contentHandler, "label", question.getLabel()); 271 XMLUtils.createElement(contentHandler, "title", question.getTitle()); 272 273 toSAXPicture(question); 274 275 String regExpType = question.getRegExpType(); 276 if (StringUtils.isNotEmpty(regExpType)) 277 { 278 XMLUtils.createElement(contentHandler, "regexp", regExpType); 279 } 280 281 String pattern = question.getRegExpPattern(); 282 if (StringUtils.isNotEmpty(pattern)) 283 { 284 XMLUtils.createElement(contentHandler, "pattern", pattern); 285 } 286 287 Map<String, String> options = question.getOptions(); 288 if (options.size() > 0) 289 { 290 AttributesImpl attr = new AttributesImpl(); 291 attr.addCDATAAttribute("other-option", String.valueOf(question.hasOtherOption())); 292 XMLUtils.startElement(contentHandler, "options", attr); 293 for (String value : options.keySet()) 294 { 295 attr = new AttributesImpl(); 296 attr.addCDATAAttribute("value", value); 297 XMLUtils.createElement(contentHandler, "option", attr, options.get(value)); 298 } 299 300 XMLUtils.endElement(contentHandler, "options"); 301 } 302 303 Map<String, String> columns = question.getColumns(); 304 if (columns.size() > 0) 305 { 306 XMLUtils.startElement(contentHandler, "columns"); 307 for (String value : columns.keySet()) 308 { 309 AttributesImpl attr = new AttributesImpl(); 310 attr.addCDATAAttribute("value", value); 311 XMLUtils.createElement(contentHandler, "column", attr, columns.get(value)); 312 } 313 XMLUtils.endElement(contentHandler, "columns"); 314 } 315 316 317 XMLUtils.endElement(contentHandler, "question"); 318 } 319 320 /** 321 * SAX the picture of the element of a survey 322 * @param elmt The survey element 323 * @throws SAXException If an error occurred 324 */ 325 protected void toSAXPicture (AbstractSurveyElement elmt) throws SAXException 326 { 327 String pictureType = elmt.getPictureType(); 328 329 if (pictureType != null) 330 { 331 AttributesImpl attrsPicture = new AttributesImpl(); 332 attrsPicture.addCDATAAttribute("pictureType", pictureType); 333 if (pictureType.equals("resource")) 334 { 335 String resourceId = elmt.getResourcePictureId(); 336 attrsPicture.addCDATAAttribute("pictureId", resourceId); 337 try 338 { 339 Resource resource = _resolver.resolveById(resourceId); 340 attrsPicture.addCDATAAttribute("pictureName", resource.getName()); 341 attrsPicture.addCDATAAttribute("pictureSize", Long.toString(resource.getLength())); 342 attrsPicture.addCDATAAttribute("imageType", "explorer"); 343 } 344 catch (UnknownAmetysObjectException e) 345 { 346 getLogger().error("The resource of id'" + resourceId + "' does not exist anymore. The picture for element survey of id '" + elmt.getId() + "' will be ignored.", e); 347 } 348 349 } 350 else if (pictureType.equals("external")) 351 { 352 BinaryMetadata picMeta = elmt.getExternalPicture(); 353 attrsPicture.addCDATAAttribute("picturePath", "picture"); 354 attrsPicture.addCDATAAttribute("pictureName", picMeta.getFilename()); 355 attrsPicture.addCDATAAttribute("pictureSize", Long.toString(picMeta.getLength())); 356 attrsPicture.addCDATAAttribute("imageType", "metadata"); 357 } 358 XMLUtils.createElement(contentHandler, "picture", attrsPicture); 359 } 360 361 XMLUtils.createElement(contentHandler, "pictureAlternative", StringUtils.defaultString(elmt.getPictureAlternative())); 362 } 363 364 365 /** 366 * Get the root node for surveys 367 * @param siteName the site name 368 * @param lang the language 369 * @return the root node 370 * @throws RepositoryException if an error occurs when retrieving the survey's root node 371 */ 372 protected ModifiableTraversableAmetysObject getSurveyRootNode (String siteName, String lang) throws RepositoryException 373 { 374 ModifiableTraversableAmetysObject pluginsNode = _siteManager.getSite(siteName).getRootPlugins(); 375 376 ModifiableTraversableAmetysObject surveyNode = null; 377 if (!pluginsNode.hasChild("survey")) 378 { 379 surveyNode = ((ModifiableTraversableAmetysObject) pluginsNode.createChild("survey", "ametys:unstructured")).createChild("ametys:surveys", "ametys:unstructured"); 380 } 381 else 382 { 383 surveyNode = pluginsNode.getChild("survey/ametys:surveys"); 384 } 385 386 if (!surveyNode.hasChild(lang)) 387 { 388 surveyNode.createChild(lang, "ametys:unstructured"); 389 ((JCRAmetysObject) pluginsNode).getNode().getSession().save(); 390 } 391 392 return pluginsNode.getChild("survey/ametys:surveys/" + lang); 393 } 394 395}