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.HashMap; 019import java.util.Map; 020 021import javax.jcr.RepositoryException; 022 023import org.apache.avalon.framework.component.Component; 024import org.apache.avalon.framework.context.Context; 025import org.apache.avalon.framework.context.ContextException; 026import org.apache.avalon.framework.context.Contextualizable; 027import org.apache.avalon.framework.service.ServiceException; 028import org.apache.avalon.framework.service.ServiceManager; 029import org.apache.avalon.framework.service.Serviceable; 030import org.apache.cocoon.Constants; 031import org.apache.cocoon.components.ContextHelper; 032import org.apache.cocoon.util.log.SLF4JLoggerAdapter; 033import org.apache.commons.lang.StringUtils; 034import org.slf4j.LoggerFactory; 035 036import org.ametys.core.observation.ObservationManager; 037import org.ametys.core.upload.Upload; 038import org.ametys.core.upload.UploadManager; 039import org.ametys.core.user.CurrentUserProvider; 040import org.ametys.core.user.UserIdentity; 041import org.ametys.core.util.JSONUtils; 042import org.ametys.plugins.explorer.resources.Resource; 043import org.ametys.plugins.repository.AmetysObject; 044import org.ametys.plugins.repository.AmetysObjectResolver; 045import org.ametys.plugins.repository.ModifiableTraversableAmetysObject; 046import org.ametys.plugins.repository.UnknownAmetysObjectException; 047import org.ametys.plugins.repository.jcr.JCRAmetysObject; 048import org.ametys.plugins.repository.metadata.BinaryMetadata; 049import org.ametys.plugins.survey.repository.AbstractSurveyElement; 050import org.ametys.plugins.survey.repository.Survey; 051import org.ametys.plugins.survey.repository.SurveyPage; 052import org.ametys.plugins.survey.repository.SurveyQuestion; 053import org.ametys.plugins.survey.repository.SurveyRule; 054import org.ametys.plugins.survey.repository.SurveyRule.RuleType; 055import org.ametys.runtime.plugin.component.AbstractLogEnabled; 056import org.ametys.web.repository.site.SiteManager; 057 058/** 059 * Abstract DAO for objects in the plugin survey. 060 * 061 */ 062public abstract class AbstractDAO extends AbstractLogEnabled implements Serviceable, Component, Contextualizable 063{ 064 /** Ametys object resolver. */ 065 protected AmetysObjectResolver _resolver; 066 /** The site manager */ 067 protected SiteManager _siteManager; 068 /** Observer manager. */ 069 protected ObservationManager _observationManager; 070 /** The current user provider. */ 071 protected CurrentUserProvider _currentUserProvider; 072 /** Manager for retrieving uploaded files */ 073 protected UploadManager _uploadManager; 074 /** JSON helper */ 075 protected JSONUtils _jsonUtils; 076 077 /** The Avalon context */ 078 protected Context _context; 079 /** The cocoon context */ 080 protected org.apache.cocoon.environment.Context _cocoonContext; 081 082 @Override 083 public void service(ServiceManager serviceManager) throws ServiceException 084 { 085 _siteManager = (SiteManager) serviceManager.lookup(SiteManager.ROLE); 086 _resolver = (AmetysObjectResolver) serviceManager.lookup(AmetysObjectResolver.ROLE); 087 _observationManager = (ObservationManager) serviceManager.lookup(ObservationManager.ROLE); 088 _currentUserProvider = (CurrentUserProvider) serviceManager.lookup(CurrentUserProvider.ROLE); 089 _uploadManager = (UploadManager) serviceManager.lookup(UploadManager.ROLE); 090 _jsonUtils = (JSONUtils) serviceManager.lookup(JSONUtils.ROLE); 091 } 092 093 @Override 094 public void contextualize(Context context) throws ContextException 095 { 096 _context = context; 097 _cocoonContext = (org.apache.cocoon.environment.Context) context.get(Constants.CONTEXT_ENVIRONMENT_CONTEXT); 098 } 099 100 /** 101 * Get the root node for surveys 102 * @param siteName the site name 103 * @param lang the language 104 * @return the root node 105 * @throws RepositoryException if an error occurs when manipulating the repository 106 */ 107 protected ModifiableTraversableAmetysObject getSurveyRootNode (String siteName, String lang) throws RepositoryException 108 { 109 ModifiableTraversableAmetysObject pluginsNode = _siteManager.getSite(siteName).getRootPlugins(); 110 111 ModifiableTraversableAmetysObject surveyNode = null; 112 if (!pluginsNode.hasChild("survey")) 113 { 114 surveyNode = ((ModifiableTraversableAmetysObject) pluginsNode.createChild("survey", "ametys:unstructured")).createChild("ametys:surveys", "ametys:unstructured"); 115 } 116 else 117 { 118 surveyNode = pluginsNode.getChild("survey/ametys:surveys"); 119 } 120 121 if (!surveyNode.hasChild(lang)) 122 { 123 surveyNode.createChild(lang, "ametys:unstructured"); 124 ((JCRAmetysObject) pluginsNode).getNode().getSession().save(); 125 } 126 127 return pluginsNode.getChild("survey/ametys:surveys/" + lang); 128 } 129 130 /** 131 * Provides the current user. 132 * @return the user which cannot be <code>null</code>. 133 */ 134 protected UserIdentity _getCurrentUser() 135 { 136 return _currentUserProvider.getUser(); 137 } 138 139 /** 140 * Update references after a survey copy 141 * @param originalSurvey The original survey 142 * @param createdSurvey The created survey 143 */ 144 protected void updateReferencesAfterCopy (Survey originalSurvey, Survey createdSurvey) 145 { 146 for (SurveyPage cPage : createdSurvey.getPages()) 147 { 148 updateReferencesAfterCopy (originalSurvey, createdSurvey, cPage); 149 } 150 } 151 152 /** 153 * Update references after copy 154 * @param originalSurvey The original survey 155 * @param createdSurvey The created survey 156 * @param createdPage The created survey page 157 */ 158 protected void updateReferencesAfterCopy (Survey originalSurvey, Survey createdSurvey, SurveyPage createdPage) 159 { 160 if (createdPage.hasRule()) 161 { 162 SurveyRule rule = createdPage.getRule(); 163 String pageId = rule.getPage(); 164 if (pageId != null) 165 { 166 try 167 { 168 // Find symmetric page in created survey 169 AmetysObject originalPage = _resolver.resolveById(pageId); 170 AmetysObject symmetricPage = createdSurvey.getChild(originalPage.getName()); 171 createdPage.setRule(rule.getType(), symmetricPage.getId()); 172 } 173 catch (UnknownAmetysObjectException e) 174 { 175 // Delete the rule 176 new SLF4JLoggerAdapter(LoggerFactory.getLogger(this.getClass())).warn("Symmetric page has not found during copy. The rule is deleted."); 177 createdPage.deleteRule(); 178 } 179 } 180 } 181 182 for (SurveyQuestion cQuestion : createdPage.getQuestions()) 183 { 184 updateReferencesAfterCopy (originalSurvey, createdSurvey, cQuestion); 185 } 186 } 187 188 /** 189 * Update references after copy 190 * @param originalSurvey The original survey 191 * @param createdSurvey The created survey 192 * @param createdQuestion The created survey question 193 */ 194 protected void updateReferencesAfterCopy (Survey originalSurvey, Survey createdSurvey, SurveyQuestion createdQuestion) 195 { 196 for (SurveyRule cRule : createdQuestion.getRules()) 197 { 198 String pageId = cRule.getPage(); 199 if (pageId != null) 200 { 201 String option = cRule.getOption(); 202 try 203 { 204 // Find symmetric page in created survey 205 AmetysObject originalPage = _resolver.resolveById(pageId); 206 AmetysObject symmetricPage = createdSurvey.getChild(originalPage.getName()); 207 208 RuleType type = cRule.getType(); 209 createdQuestion.deleteRule(option); 210 createdQuestion.addRules(option, type, symmetricPage.getId()); 211 } 212 catch (UnknownAmetysObjectException e) 213 { 214 // Delete rule 215 new SLF4JLoggerAdapter(LoggerFactory.getLogger(this.getClass())).warn("Symmetric page has not found during copy. The rule is deleted."); 216 createdQuestion.deleteRule(option); 217 } 218 } 219 } 220 } 221 222 /** 223 * Set the picture 224 * @param elmt The survey element 225 * @param valueAsStr The value as String 226 */ 227 protected void setPicture (AbstractSurveyElement elmt, String valueAsStr) 228 { 229 if (StringUtils.isNotEmpty(valueAsStr)) 230 { 231 Map<String, Object> picture = _jsonUtils.convertJsonToMap(valueAsStr); 232 233 if (!picture.isEmpty()) 234 { 235 String pictureType = (String) picture.get("type"); 236 String value = (String) picture.get("id"); 237 238 if (pictureType.equals("explorer") && !"untouched".equals(value)) 239 { 240 elmt.setResourcePicture(value); 241 } 242 else if (!"untouched".equals(value)) 243 { 244 UserIdentity user = _currentUserProvider.getUser(); 245 Upload upload = _uploadManager.getUpload(user, value); 246 247 String filename = upload.getFilename(); 248 String mimeType = upload.getMimeType() != null ? upload.getMimeType() : _cocoonContext.getMimeType(filename); 249 String finalMimeType = mimeType != null ? mimeType : "application/unknown"; 250 251 elmt.setExternalPicture(finalMimeType, filename, upload.getInputStream()); 252 } 253 } 254 else 255 { 256 // Remove picture 257 elmt.setNoPicture(); 258 } 259 260 } 261 else 262 { 263 // Remove picture 264 elmt.setNoPicture(); 265 } 266 } 267 268 /** 269 * Get the information about picture 270 * @param elmt The survey element 271 * @return The picture 272 */ 273 protected Map<String, Object> getPictureInfo (AbstractSurveyElement elmt) 274 { 275 Map<String, Object> properties = new HashMap<>(); 276 277 properties.put("pictureAlternative", StringUtils.defaultString(elmt.getPictureAlternative())); 278 279 Map<String, Object> pictureInfos = new HashMap<>(); 280 String pictureType = elmt.getPictureType(); 281 282 if (StringUtils.isNotBlank(pictureType)) 283 { 284 if (pictureType.equals("resource")) 285 { 286 String resourceId = elmt.getResourcePictureId(); 287 pictureInfos.put("id", resourceId); 288 try 289 { 290 Resource resource = _resolver.resolveById(resourceId); 291 292 pictureInfos.put("filename", resource.getName()); 293 pictureInfos.put("size", resource.getLength()); 294 pictureInfos.put("type", "explorer"); 295 pictureInfos.put("lastModified", resource.getLastModified()); 296 297 String contextPath = ContextHelper.getRequest(_context).getContextPath(); 298 String viewUrl = contextPath + "/plugins/explorer/resource?id=" + resource.getId(); 299 String downloadUrl = viewUrl + "&download=true"; 300 pictureInfos.put("viewUrl", viewUrl); 301 pictureInfos.put("downloadUrl", downloadUrl); 302 } 303 catch (UnknownAmetysObjectException e) 304 { 305 getLogger().error("The resource of id'" + resourceId + "' does not exist anymore. The picture for element of id '" + elmt.getId() + "' will be ignored.", e); 306 properties.put("pictureNotFound", true); 307 } 308 } 309 else if (pictureType.equals("external")) 310 { 311 BinaryMetadata picMeta = elmt.getExternalPicture(); 312 313 pictureInfos.put("path", AbstractSurveyElement.PROPERTY_PICTURE); 314 pictureInfos.put("filename", picMeta.getFilename()); 315 pictureInfos.put("size", picMeta.getLength()); 316 pictureInfos.put("lastModified", picMeta.getLastModified()); 317 pictureInfos.put("type", "metadata"); 318 319 String contextPath = ContextHelper.getRequest(_context).getContextPath(); 320 String viewUrl = contextPath + "/plugins/cms/binaryMetadata/" + AbstractSurveyElement.PROPERTY_PICTURE + "?objectId=" + elmt.getId(); 321 String downloadUrl = viewUrl + "&download=true"; 322 pictureInfos.put("viewUrl", viewUrl); 323 pictureInfos.put("downloadUrl", downloadUrl); 324 325 } 326 } 327 328 properties.put("picture", pictureInfos); 329 330 return properties; 331 } 332 333}