001/* 002 * Copyright 2020 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.mobileapp; 017 018import java.util.HashMap; 019import java.util.List; 020import java.util.Map; 021 022import org.apache.avalon.framework.component.Component; 023import org.apache.avalon.framework.service.ServiceException; 024import org.apache.avalon.framework.service.ServiceManager; 025import org.apache.avalon.framework.service.Serviceable; 026import org.apache.commons.lang3.StringUtils; 027 028import org.ametys.core.util.I18nUtils; 029import org.ametys.plugins.workspaces.ObservationConstants; 030import org.ametys.plugins.workspaces.project.ProjectsCatalogueManager; 031import org.ametys.plugins.workspaces.project.objects.Project; 032import org.ametys.runtime.i18n.I18nizableText; 033import org.ametys.runtime.i18n.I18nizableTextParameter; 034import org.ametys.runtime.plugin.component.AbstractLogEnabled; 035 036/** 037 * Helper to handle project feeds 038 */ 039public class FeedHelper extends AbstractLogEnabled implements Serviceable, Component 040{ 041 /** Avalon Role */ 042 public static final String ROLE = FeedHelper.class.getName(); 043 044 /** I18N Utils */ 045 protected I18nUtils _i18nUtils; 046 047 /** The project catalogue manager component */ 048 protected ProjectsCatalogueManager _projectsCatalogueManager; 049 050 public void service(ServiceManager manager) throws ServiceException 051 { 052 _i18nUtils = (I18nUtils) manager.lookup(I18nUtils.ROLE); 053 _projectsCatalogueManager = (ProjectsCatalogueManager) manager.lookup(ProjectsCatalogueManager.ROLE); 054 } 055 056 057 /** 058 * Generate a map of project names with the basic projects informations to return 059 * @return a map of basic information about projects 060 */ 061 public Map<String, Map<String, Object>> getProjects() 062 { 063 Map<String, Map<String, Object>> result = new HashMap<>(); 064 List<Map<String, Object>> userProjects = _projectsCatalogueManager.getUserProjects(); 065 for (Map<String, Object> fullProjectMap : userProjects) 066 { 067 String name = (String) fullProjectMap.get("name"); 068 Map<String, Object> neededInfos = new HashMap<>(); 069 070 neededInfos.put("name", name); 071 neededInfos.put("description", fullProjectMap.get("description")); 072 neededInfos.put("title", fullProjectMap.get("title")); 073 neededInfos.put("url", fullProjectMap.get("url")); 074 neededInfos.put("illustration", fullProjectMap.get("illustration")); 075 neededInfos.put("id", fullProjectMap.get("id")); 076 neededInfos.put("category", fullProjectMap.get("category")); 077 078 result.put(name, neededInfos); 079 } 080 081 return result; 082 } 083 084 /** 085 * Transform a {@link Project} into a json map 086 * @param project the project to parse 087 * @return a json map 088 */ 089 public Map<String, Object> projectToMap(Project project) 090 { 091 return _projectsCatalogueManager.detailedProject2json(project); 092 } 093 /** 094 * Add infos to the event, so it can be displayed by the app 095 * @param event the event to parse 096 * @param project the project, as a json map (see {@link FeedHelper#projectToMap(Project)}) 097 * @param lang language to use to translate the short description 098 * @return a map to return in json 099 */ 100 public Map<String, Object> getEventInfos(Map<String, Object> event, Map<String, Object> project, String lang) 101 { 102 Map<String, Object> result = new HashMap<>(); 103 104 result.putAll(event); 105 106 result.put("project", project); 107 108 @SuppressWarnings("unchecked") 109 Map<String, String> author = new HashMap<>((Map<String, String>) event.get("author")); 110 author.put("avatarUrl", "/_plugins/workspaces/user/" + author.get("populationId") + "/" + author.get("login") + "/image_" + PostConstants.IMAGE_SIZE); 111 result.put("author", author); 112 113 result.put("short-description", getEventDescription(event, lang)); 114 115 result.put("content_id", getEventObjectId(event)); 116 result.put("content_url", getEventUrl(event)); 117 118 return result; 119 } 120 121 /** 122 * Generate a description for this event 123 * @param event the event to describe 124 * @return a String of the description 125 */ 126 @SuppressWarnings("unchecked") 127 protected String getEventObjectId(Map<String, Object> event) 128 { 129 String id = null; 130 String eventType = (String) event.get("type"); 131 132 switch (eventType) 133 { 134 /* 135 * RESOURCES 136 */ 137 case org.ametys.plugins.explorer.ObservationConstants.EVENT_RESOURCE_CREATED : 138 case org.ametys.plugins.explorer.ObservationConstants.EVENT_RESOURCE_UPDATED : 139 case org.ametys.plugins.explorer.ObservationConstants.EVENT_RESOURCE_RENAMED : 140 id = (String) ((Map<String, Object>) event.get("file")).get("id"); 141 break; 142 143 /* 144 * CALENDAR 145 */ 146 case org.ametys.plugins.explorer.ObservationConstants.EVENT_CALENDAR_EVENT_CREATED : 147 case org.ametys.plugins.explorer.ObservationConstants.EVENT_CALENDAR_EVENT_UPDATED : 148 id = (String) event.get("eventId"); 149 break; 150 151 /* 152 * THREAD 153 */ 154 case org.ametys.plugins.explorer.ObservationConstants.EVENT_THREAD_CREATED : 155 case org.ametys.plugins.explorer.ObservationConstants.EVENT_THREAD_POST_CREATED : 156 id = (String) event.get("threadId"); 157 break; 158 159 /* 160 * MEMBER 161 */ 162 case ObservationConstants.EVENT_MEMBER_ADDED : 163 // no id available 164 break; 165 case ObservationConstants.EVENT_WALLCONTENT_ADDED : 166 id = (String) event.get("contentId"); 167 break; 168 169 /** 170 * WIKI 171 */ 172 case ObservationConstants.EVENT_EDITIONFO_CREATED : 173 case ObservationConstants.EVENT_EDITIONFO_UPDATED : 174 case ObservationConstants.EVENT_EDITIONFO_RENAMED : 175 case ObservationConstants.EVENT_EDITIONFO_DELETED : 176 id = (String) event.get("pageId"); 177 break; 178 179 /** 180 * TASK 181 */ 182 case org.ametys.plugins.explorer.ObservationConstants.EVENT_TASK_CREATED : 183 case org.ametys.plugins.explorer.ObservationConstants.EVENT_TASK_ASSIGNED : 184 case org.ametys.plugins.explorer.ObservationConstants.EVENT_TASK_STATUS_CHANGED : 185 id = (String) event.get("taskId"); 186 break; 187 default: 188 break; 189 } 190 191 return id; 192 } 193 194 195 /** 196 * Generate a description for this event 197 * @param event the event to describe 198 * @return a String of the description 199 */ 200 protected String getEventUrl(Map<String, Object> event) 201 { 202 String url = null; 203 String eventType = (String) event.get("type"); 204 205 switch (eventType) 206 { 207 /* 208 * RESOURCES 209 */ 210 case org.ametys.plugins.explorer.ObservationConstants.EVENT_RESOURCE_CREATED : 211 case org.ametys.plugins.explorer.ObservationConstants.EVENT_RESOURCE_UPDATED : 212 case org.ametys.plugins.explorer.ObservationConstants.EVENT_RESOURCE_RENAMED : 213 url = (String) event.get("parentFolderUrl"); 214 break; 215 216 /* 217 * CALENDAR 218 */ 219 case org.ametys.plugins.explorer.ObservationConstants.EVENT_CALENDAR_EVENT_CREATED : 220 case org.ametys.plugins.explorer.ObservationConstants.EVENT_CALENDAR_EVENT_UPDATED : 221 url = (String) event.get("eventUrl"); 222 break; 223 224 /* 225 * THREAD 226 */ 227 case org.ametys.plugins.explorer.ObservationConstants.EVENT_THREAD_CREATED : 228 case org.ametys.plugins.explorer.ObservationConstants.EVENT_THREAD_POST_CREATED : 229 url = (String) event.get("threadUrl"); 230 break; 231 232 /* 233 * MEMBER 234 */ 235 case ObservationConstants.EVENT_MEMBER_ADDED : 236 // no url available 237 break; 238 case ObservationConstants.EVENT_WALLCONTENT_ADDED : 239 // no url available 240 break; 241 242 /** 243 * WIKI 244 */ 245 case ObservationConstants.EVENT_EDITIONFO_CREATED : 246 case ObservationConstants.EVENT_EDITIONFO_UPDATED : 247 case ObservationConstants.EVENT_EDITIONFO_RENAMED : 248 case ObservationConstants.EVENT_EDITIONFO_DELETED : 249 url = (String) event.get("pageUrl"); 250 break; 251 252 /** 253 * TASK 254 */ 255 case org.ametys.plugins.explorer.ObservationConstants.EVENT_TASK_CREATED : 256 case org.ametys.plugins.explorer.ObservationConstants.EVENT_TASK_ASSIGNED : 257 case org.ametys.plugins.explorer.ObservationConstants.EVENT_TASK_STATUS_CHANGED : 258 url = (String) event.get("taskUrl"); 259 break; 260 default: 261 break; 262 } 263 if (StringUtils.isBlank(url)) 264 { 265 url = (String) event.get("projectUrl"); 266 } 267 return url; 268 } 269 270 /** 271 * Generate a description for this event 272 * @param event the event to describe 273 * @param lang the language to use 274 * @return a String of the description 275 */ 276 @SuppressWarnings("unchecked") 277 protected String getEventDescription(Map<String, Object> event, String lang) 278 { 279 String description = null; 280 281 String eventType = (String) event.get("type"); 282 283 Integer amount = (Integer) event.get("amount"); 284 String i18nKey = null; 285 Map<String, I18nizableTextParameter> parameters = new HashMap<>(); 286 parameters.put("author", new I18nizableText(((Map<String, String>) event.get("author")).get("fullname"))); 287 parameters.put("project", new I18nizableText((String) event.get("projectTitle"))); 288 parameters.put("nb", new I18nizableText(amount.toString())); 289 290 switch (eventType) 291 { 292 293 /* 294 * RESOURCES 295 */ 296 case org.ametys.plugins.explorer.ObservationConstants.EVENT_RESOURCE_CREATED : 297 parameters.put("folder", new I18nizableText((String) event.get("parentFolder"))); 298 if (amount == 1) 299 { 300 i18nKey = "PLUGINS_WORKSPACES_PROJECT_SERVICE_ACTIVITY_STREAM_EVENT_DOCUMENT_ADDED_DESC"; 301 } 302 else 303 { 304 i18nKey = "PLUGINS_WORKSPACES_PROJECT_SERVICE_ACTIVITY_STREAM_EVENT_DOCUMENT_ADDED_MULTI_DESC"; 305 } 306 break; 307 case org.ametys.plugins.explorer.ObservationConstants.EVENT_RESOURCE_UPDATED : 308 parameters.put("folder", new I18nizableText((String) event.get("parentFolder"))); 309 if (amount == 1) 310 { 311 i18nKey = "PLUGINS_WORKSPACES_PROJECT_SERVICE_ACTIVITY_STREAM_EVENT_DOCUMENT_UPDATED_DESC"; 312 } 313 else 314 { 315 i18nKey = "PLUGINS_WORKSPACES_PROJECT_SERVICE_ACTIVITY_STREAM_EVENT_DOCUMENT_UPDATED_MULTI_DESC"; 316 } 317 break; 318 case org.ametys.plugins.explorer.ObservationConstants.EVENT_RESOURCE_RENAMED : 319 parameters.put("folder", new I18nizableText((String) event.get("parentFolder"))); 320 if (amount == 1) 321 { 322 i18nKey = "PLUGINS_WORKSPACES_PROJECT_SERVICE_ACTIVITY_STREAM_EVENT_DOCUMENT_RENAMED_DESC"; 323 } 324 else 325 { 326 i18nKey = "PLUGINS_WORKSPACES_PROJECT_SERVICE_ACTIVITY_STREAM_EVENT_DOCUMENT_RENAMED_MULTI_DESC"; 327 } 328 break; 329 330 /* 331 * CALENDAR 332 */ 333 case org.ametys.plugins.explorer.ObservationConstants.EVENT_CALENDAR_EVENT_CREATED : 334 parameters.put("calendar", new I18nizableText((String) event.get("calendarTitle"))); 335 if (amount == 1) 336 { 337 parameters.put("event", new I18nizableText(getTitles(event, "events", "eventTitle"))); 338 i18nKey = "PLUGINS_WORKSPACES_PROJECT_SERVICE_ACTIVITY_STREAM_EVENT_CALENDAR_ADDED_DESC"; 339 } 340 else 341 { 342 parameters.put("events", new I18nizableText(getTitles(event, "events", "eventTitle"))); 343 i18nKey = "PLUGINS_WORKSPACES_PROJECT_SERVICE_ACTIVITY_STREAM_EVENT_CALENDAR_ADDED_MULTI_DESC"; 344 } 345 break; 346 case org.ametys.plugins.explorer.ObservationConstants.EVENT_CALENDAR_EVENT_UPDATED : 347 parameters.put("calendar", new I18nizableText((String) event.get("calendarTitle"))); 348 if (amount == 1) 349 { 350 parameters.put("event", new I18nizableText(getTitles(event, "events", "eventTitle"))); 351 i18nKey = "PLUGINS_WORKSPACES_PROJECT_SERVICE_ACTIVITY_STREAM_EVENT_CALENDAR_UPDATED_DESC"; 352 } 353 else 354 { 355 parameters.put("events", new I18nizableText(getTitles(event, "events", "eventTitle"))); 356 i18nKey = "PLUGINS_WORKSPACES_PROJECT_SERVICE_ACTIVITY_STREAM_EVENT_CALENDAR_UPDATED_MULTI_DESC"; 357 } 358 break; 359 360 /* 361 * THREAD 362 */ 363 case org.ametys.plugins.explorer.ObservationConstants.EVENT_THREAD_CREATED : 364 if (amount == 1) 365 { 366 parameters.put("thread", new I18nizableText(getTitles(event, "threads", "threadTitle"))); 367 i18nKey = "PLUGINS_WORKSPACES_PROJECT_SERVICE_ACTIVITY_STREAM_EVENT_THREAD_CREATED_DESC"; 368 } 369 else 370 { 371 parameters.put("threads", new I18nizableText(getTitles(event, "threads", "threadTitle"))); 372 i18nKey = "PLUGINS_WORKSPACES_PROJECT_SERVICE_ACTIVITY_STREAM_EVENT_THREAD_CREATED_MULTI_DESC"; 373 } 374 break; 375 case org.ametys.plugins.explorer.ObservationConstants.EVENT_THREAD_POST_CREATED : 376 parameters.put("thread", new I18nizableText(getTitles(event, "threads", "threadTitle"))); 377 i18nKey = "PLUGINS_WORKSPACES_PROJECT_SERVICE_ACTIVITY_STREAM_EVENT_THREAD_POST_CREATED_DESC"; 378 break; 379 380 /* 381 * MEMBER 382 */ 383 case ObservationConstants.EVENT_MEMBER_ADDED : 384 if (amount == 1) 385 { 386 parameters.put("member", new I18nizableText((String) event.get("member"))); 387 i18nKey = "PLUGINS_WORKSPACES_PROJECT_SERVICE_ACTIVITY_STREAM_EVENT_MEMBER_ADDED_DESC"; 388 } 389 else 390 { 391 List<String> members = (List<String>) event.get("members"); 392 parameters.put("members", new I18nizableText(String.join(", ", members))); 393 i18nKey = "PLUGINS_WORKSPACES_PROJECT_SERVICE_ACTIVITY_STREAM_EVENT_MEMBERS_ADDED_DESC"; 394 } 395 break; 396 case ObservationConstants.EVENT_WALLCONTENT_ADDED : 397 i18nKey = "PLUGINS_WORKSPACES_PROJECT_SERVICE_ACTIVITY_STREAM_EVENT_WALLCONTENT_ADDED_DESC"; 398 break; 399 400 /** 401 * WIKI 402 */ 403 case ObservationConstants.EVENT_EDITIONFO_CREATED : 404 if (amount == 1) 405 { 406 parameters.put("page", new I18nizableText(getTitles(event, "pages", "pageTitle"))); 407 i18nKey = "PLUGINS_WORKSPACES_PROJECT_SERVICE_ACTIVITY_STREAM_EVENT_PAGE_CREATED_DESC"; 408 } 409 else 410 { 411 parameters.put("pages", new I18nizableText(getTitles(event, "pages", "pageTitle"))); 412 i18nKey = "PLUGINS_WORKSPACES_PROJECT_SERVICE_ACTIVITY_STREAM_EVENT_PAGES_CREATED_DESC"; 413 } 414 break; 415 case ObservationConstants.EVENT_EDITIONFO_UPDATED : 416 if (amount == 1) 417 { 418 parameters.put("page", new I18nizableText(getTitles(event, "pages", "pageTitle"))); 419 i18nKey = "PLUGINS_WORKSPACES_PROJECT_SERVICE_ACTIVITY_STREAM_EVENT_PAGE_UPDATED_DESC"; 420 } 421 else 422 { 423 parameters.put("pages", new I18nizableText(getTitles(event, "pages", "pageTitle"))); 424 i18nKey = "PLUGINS_WORKSPACES_PROJECT_SERVICE_ACTIVITY_STREAM_EVENT_PAGES_UPDATED_DESC"; 425 } 426 break; 427 case ObservationConstants.EVENT_EDITIONFO_RENAMED : 428 parameters.put("oldTitle", new I18nizableText((String) event.get("pageOldTitle"))); 429 parameters.put("title", new I18nizableText((String) event.get("pageTitle"))); 430 i18nKey = "PLUGINS_WORKSPACES_PROJECT_SERVICE_ACTIVITY_STREAM_EVENT_PAGE_RENAMED_DESC"; 431 break; 432 case ObservationConstants.EVENT_EDITIONFO_DELETED : 433 if (amount == 1) 434 { 435 parameters.put("page", new I18nizableText(getTitles(event, "pages", "pageTitle"))); 436 i18nKey = "PLUGINS_WORKSPACES_PROJECT_SERVICE_ACTIVITY_STREAM_EVENT_PAGE_DELETED_DESC"; 437 } 438 else 439 { 440 parameters.put("pages", new I18nizableText(getTitles(event, "pages", "pageTitle"))); 441 i18nKey = "PLUGINS_WORKSPACES_PROJECT_SERVICE_ACTIVITY_STREAM_EVENT_PAGES_DELETED_DESC"; 442 } 443 break; 444 445 /** 446 * TASK 447 */ 448 case org.ametys.plugins.explorer.ObservationConstants.EVENT_TASK_CREATED : 449 if (amount == 1) 450 { 451 parameters.put("task", new I18nizableText(getTitles(event, "tasks", "taskTitle"))); 452 i18nKey = "PLUGINS_WORKSPACES_PROJECT_SERVICE_ACTIVITY_STREAM_EVENT_TASK_ADDED_DESC"; 453 } 454 else 455 { 456 parameters.put("tasks", new I18nizableText(getTitles(event, "tasks", "taskTitle"))); 457 i18nKey = "PLUGINS_WORKSPACES_PROJECT_SERVICE_ACTIVITY_STREAM_EVENT_TASKS_ADDED_DESC"; 458 } 459 break; 460 case org.ametys.plugins.explorer.ObservationConstants.EVENT_TASK_ASSIGNED : 461 parameters.put("task", new I18nizableText((String) event.get("taskTitle"))); 462 parameters.put("assignee", new I18nizableText((String) event.get("assignees"))); 463 i18nKey = "PLUGINS_WORKSPACES_PROJECT_SERVICE_ACTIVITY_STREAM_EVENT_TASK_ASSIGNED_DESC"; 464 break; 465 case org.ametys.plugins.explorer.ObservationConstants.EVENT_TASK_STATUS_CHANGED : 466 parameters.put("task", new I18nizableText((String) event.get("taskTitle"))); 467 parameters.put("status", new I18nizableText((String) event.get("status"))); 468 i18nKey = "PLUGINS_WORKSPACES_PROJECT_SERVICE_ACTIVITY_STREAM_EVENT_TASK_STATUS_CHANGED_DESC"; 469 break; 470 default: 471 break; 472 } 473 474 if (i18nKey != null) 475 { 476 I18nizableText descriptionI18n = new I18nizableText("plugin.workspaces", i18nKey, parameters); 477 description = _i18nUtils.translate(descriptionI18n, lang); 478 } 479 480 return description; 481 } 482 483 /** 484 * Aggregates a list of elements from the event. 485 * event = { 486 * mapKey : [ 487 * { 488 * titleKey : "Title 1", 489 * … 490 * }, 491 * { 492 * titleKey : "Title 2", 493 * … 494 * }, 495 * { 496 * titleKey : "Title 3", 497 * … 498 * } 499 * ], 500 * … 501 * } 502 * @param event the event to use 503 * @param mapKey the key of the list to use 504 * @param titleKey title to use from the map 505 * @return a list, separated with commas, between each titles 506 */ 507 protected String getTitles(Map<String, Object> event, String mapKey, String titleKey) 508 { 509 @SuppressWarnings("unchecked") 510 List<Map<String, String>> items = (List<Map<String, String>>) event.get(mapKey); 511 512 String result = null; 513 514 for (Map<String, String> item : items) 515 { 516 if (result == null) 517 { 518 result = item.get(titleKey); 519 } 520 else 521 { 522 result += ", " + item.get(titleKey); 523 } 524 } 525 526 return result; 527 } 528 529}