001/* 002 * Copyright 2013 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.cart; 017 018import java.time.ZonedDateTime; 019import java.util.ArrayList; 020import java.util.Collections; 021import java.util.HashSet; 022import java.util.List; 023import java.util.Set; 024import java.util.stream.Collectors; 025 026import javax.jcr.Node; 027import javax.jcr.RepositoryException; 028 029import org.apache.commons.lang3.ArrayUtils; 030import org.slf4j.Logger; 031import org.slf4j.LoggerFactory; 032 033import org.ametys.cms.indexing.solr.SolrAclCacheUninfluentialObject; 034import org.ametys.cms.repository.Content; 035import org.ametys.cms.repository.DefaultIndexableAmetysObject; 036import org.ametys.core.user.UserIdentity; 037import org.ametys.plugins.explorer.resources.Resource; 038import org.ametys.plugins.queriesdirectory.Query; 039import org.ametys.plugins.repository.AmetysObject; 040import org.ametys.plugins.repository.AmetysRepositoryException; 041import org.ametys.plugins.repository.UnknownAmetysObjectException; 042import org.ametys.plugins.repository.data.holder.group.ModifiableRepeater; 043import org.ametys.plugins.repository.data.holder.group.ModifiableRepeaterEntry; 044 045/** 046 * Class representing a cart, backed by a JCR node.<br> 047 */ 048@SolrAclCacheUninfluentialObject 049public class Cart extends DefaultIndexableAmetysObject<CartFactory> 050{ 051 /** Property name for cart title */ 052 public static final String TITLE = "label"; 053 /** Property name for cart description */ 054 public static final String DESCRIPTION = "description"; 055 /** Property name for cart documentation */ 056 public static final String DOCUMENTATION = "documentation"; 057 /** Property name for cart author */ 058 public static final String AUTHOR = "author"; 059 /** Property name for cart last contributor */ 060 public static final String CONTRIBUTOR = "contributor"; 061 /** Property name for cart creation date */ 062 public static final String CREATIONDATE = "creationDate"; 063 /** Property name for cart last modification date */ 064 public static final String LASTMODIFICATIONDATE = "lastModificationDate"; 065 066 /** Property name for cart content elements */ 067 public static final String CONTENT_CART_ELEMENTS = "contents"; 068 /** Property name for cart resource elements */ 069 public static final String RESOURCE_CART_ELEMENTS = "resources"; 070 /** Property name for cart queries elements */ 071 public static final String QUERIES_CART_ELEMENTS = "queries"; 072 /** Property name for cart queries from directory elements */ 073 public static final String QUERIES_FROM_DIRECTORY_CART_ELEMENTS = "queries-from-directory"; 074 075 /** Property name for cart query id */ 076 public static final String QUERY_ID_PROPERTY = "id"; 077 /** Property name for cart query description */ 078 public static final String QUERY_DESCRIPTION_PROPERTY = "description"; 079 /** Property name for cart query author */ 080 public static final String QUERY_AUTHOR_PROPERTY = "author"; 081 /** Property name for cart query title */ 082 public static final String QUERY_TITLE_PROPERTY = "title"; 083 /** Property name for cart query creation date */ 084 public static final String QUERY_DATE_PROPERTY = "date"; 085 086 private static Logger _logger = LoggerFactory.getLogger(Cart.class.getName()); 087 088 /** 089 * Rights profiles 090 */ 091 public enum CartProfile 092 { 093 /** Read access */ 094 READ_ACCESS, 095 /** Write access */ 096 WRITE_ACCESS, 097 /** Right access */ 098 RIGHT_ACCESS; 099 100 @Override 101 public String toString() 102 { 103 return name().toLowerCase(); 104 } 105 } 106 107 /** 108 * Types of CartElement 109 */ 110 public enum CartElementType 111 { 112 /** Type: content. */ 113 CONTENT, 114 /** Type: resource. */ 115 RESOURCE, 116 /** Type: cartQuery. */ 117 CARTQUERY, 118 /** Type: query from directory. */ 119 CARTQUERYFROMDIRECTORY 120 } 121 122 /** 123 * Creates an {@link Cart}. 124 * @param node the node backing this {@link AmetysObject} 125 * @param parentPath the parentPath in the Ametys hierarchy 126 * @param factory the DefaultAmetysObjectFactory which created the AmetysObject 127 */ 128 public Cart(Node node, String parentPath, CartFactory factory) 129 { 130 super(node, parentPath, factory); 131 } 132 133 /** 134 * Set the title of this cart. 135 * @param title the title 136 */ 137 public void setTitle(String title) 138 { 139 this.setValue(TITLE, title); 140 } 141 142 /** 143 * Set the description of this cart. 144 * @param description the description 145 */ 146 public void setDescription(String description) 147 { 148 this.setValue(DESCRIPTION, description); 149 } 150 151 /** 152 * Set the documentation of this cart. 153 * @param documentation the documentation 154 */ 155 public void setDocumentation(String documentation) 156 { 157 this.setValue(DOCUMENTATION, documentation); 158 } 159 160 /** 161 * Set the author of this cart. 162 * @param author the author 163 */ 164 public void setAuthor(UserIdentity author) 165 { 166 this.setValue(AUTHOR, author); 167 } 168 169 /** 170 * Set the last contributor of this cart. 171 * @param contributor the last contributor 172 */ 173 public void setContributor(UserIdentity contributor) 174 { 175 this.setValue(CONTRIBUTOR, contributor); 176 } 177 178 /** 179 * Set the date of the creation. 180 * @param creationDate the last modification date to set. 181 */ 182 public void setCreationDate(ZonedDateTime creationDate) 183 { 184 this.setValue(CREATIONDATE, creationDate); 185 } 186 187 /** 188 * Set the date of the last modification. 189 * @param lastModificationDate the last modification date to set. 190 */ 191 public void setLastModificationDate(ZonedDateTime lastModificationDate) 192 { 193 this.setValue(LASTMODIFICATIONDATE, lastModificationDate); 194 } 195 196 /** 197 * Get the title of the cart 198 * @return The title 199 */ 200 public String getTitle() 201 { 202 return this.getValue(TITLE); 203 } 204 205 /** 206 * Get the description of the cart 207 * @return The description 208 */ 209 public String getDescription() 210 { 211 return this.getValue(DESCRIPTION); 212 } 213 214 /** 215 * Get the documentation of the cart 216 * @return The documentation 217 */ 218 public String getDocumentation() 219 { 220 return this.getValue(DOCUMENTATION); 221 } 222 223 /** 224 * Get the author of the cart 225 * @return The author 226 */ 227 public UserIdentity getAuthor() 228 { 229 return this.getValue(AUTHOR); 230 } 231 232 /** 233 * Get the last contributor of the cart 234 * @return The contributor 235 */ 236 public UserIdentity getContributor() 237 { 238 return this.getValue(CONTRIBUTOR); 239 } 240 241 /** 242 * Get the date of the last modification of the cart 243 * @return The date 244 */ 245 public ZonedDateTime getCreationDate() 246 { 247 return this.getValue(CREATIONDATE); 248 } 249 250 /** 251 * Get the date of the last modification of the cart 252 * @return The date 253 */ 254 public ZonedDateTime getLastModificationDate() 255 { 256 return this.getValue(LASTMODIFICATIONDATE); 257 } 258 259 /** 260 * Add a content to the cart 261 * @param contentId The content id 262 */ 263 public void addContent (String contentId) 264 { 265 _addElementToCart(contentId, CONTENT_CART_ELEMENTS); 266 } 267 268 /** 269 * Add a resource to the cart 270 * @param resourceId The resource id 271 */ 272 public void addResource (String resourceId) 273 { 274 _addElementToCart(resourceId, RESOURCE_CART_ELEMENTS); 275 } 276 277 /** 278 * Add a query from directory to the cart 279 * @param queryId The query id 280 */ 281 public void addQueryFormDirectory (String queryId) 282 { 283 _addElementToCart(queryId, QUERIES_FROM_DIRECTORY_CART_ELEMENTS); 284 } 285 286 private void _addElementToCart(String elementId, String attributePath) 287 { 288 String[] elmtArray = getValueOrDefault(attributePath, new String[0]); 289 Set<String> elmts = new HashSet<>(); 290 Collections.addAll(elmts, elmtArray); 291 elmts.add(elementId); 292 setValue(attributePath, elmts.toArray(new String[elmts.size()])); 293 } 294 295 /** 296 * Add a query to the cart 297 * @param author The author of the query 298 * @param title The title of the query 299 * @param description The query as string 300 */ 301 public void addQuery (UserIdentity author, String title, String description) 302 { 303 addQuery(org.ametys.core.util.StringUtils.generateKey(), author, title, description, ZonedDateTime.now()); 304 } 305 306 /** 307 * Add a query to the cart 308 * @param id The id of the query 309 * @param author The author of the query 310 * @param title The title of the query 311 * @param description The query as string 312 * @param date The creation date of the query 313 */ 314 public void addQuery (String id, UserIdentity author, String title, String description, ZonedDateTime date) 315 { 316 ModifiableRepeater queries = getRepeater(QUERIES_CART_ELEMENTS, true); 317 ModifiableRepeaterEntry query = queries.addEntry(); 318 query.setValue(QUERY_ID_PROPERTY, id); 319 query.setValue(QUERY_TITLE_PROPERTY, title); 320 query.setValue(QUERY_DESCRIPTION_PROPERTY, description); 321 query.setValue(QUERY_AUTHOR_PROPERTY, author); 322 query.setValue(QUERY_DATE_PROPERTY, date); 323 } 324 325 /** 326 * Delete an element 327 * @param elmtId The id of element to remove 328 * @param elmtType The type of element to remove 329 */ 330 public void removeElement (String elmtId, CartElementType elmtType) 331 { 332 switch (elmtType) 333 { 334 case CONTENT: 335 _removeContent(elmtId); 336 break; 337 338 case RESOURCE: 339 _removeResource(elmtId); 340 break; 341 342 case CARTQUERY: 343 _removeQuery(elmtId); 344 break; 345 346 case CARTQUERYFROMDIRECTORY: 347 _removeQueryFromDirectory(elmtId); 348 break; 349 350 default: 351 break; 352 } 353 } 354 355 /** 356 * Remove a resource from the cart 357 * @param resourceIdToRemove The id of the resource to remove 358 */ 359 protected void _removeResource(String resourceIdToRemove) 360 { 361 _removeElementFromCart(resourceIdToRemove, RESOURCE_CART_ELEMENTS); 362 } 363 364 /** 365 * Remove a content from the cart 366 * @param contentIdToRemove The id of the content to remove 367 */ 368 protected void _removeContent(String contentIdToRemove) 369 { 370 _removeElementFromCart(contentIdToRemove, CONTENT_CART_ELEMENTS); 371 } 372 373 /** 374 * Remove a query from directory from the cart 375 * @param queryIdToRemove The id of the query from directory to remove 376 */ 377 protected void _removeQueryFromDirectory(String queryIdToRemove) 378 { 379 _removeElementFromCart(queryIdToRemove, QUERIES_FROM_DIRECTORY_CART_ELEMENTS); 380 } 381 382 private void _removeElementFromCart(String elementId, String attributePath) 383 { 384 String[] elements = getValueOrDefault(attributePath, new String[0]); 385 elements = ArrayUtils.removeElement(elements, elementId); 386 setValue(attributePath, elements); 387 } 388 389 /** 390 * Remove a query from the cart 391 * @param queryIdToRemove The id of the query to remove 392 */ 393 protected void _removeQuery(String queryIdToRemove) 394 { 395 ModifiableRepeater queries = getRepeater(QUERIES_CART_ELEMENTS, true); 396 ModifiableRepeaterEntry entryToRemove = queries.getEntries() 397 .stream() 398 .filter(entry -> entry.getValue(QUERY_ID_PROPERTY).equals(queryIdToRemove)) 399 .findFirst() 400 .orElse(null); 401 402 if (entryToRemove != null) 403 { 404 queries.removeEntry(entryToRemove.getPosition()); 405 } 406 } 407 408 /** 409 * Get the elements of the cart 410 * @return The elements of the cart 411 */ 412 public List<CartElement> getElements () 413 { 414 List<CartElement> elmts = new ArrayList<>(); 415 416 try 417 { 418 elmts.addAll(getContentCartElements()); 419 elmts.addAll(getResourceCartElements()); 420 elmts.addAll(getQueryCartElements()); 421 elmts.addAll(getQueryFromDirectoryCartElements()); 422 } 423 catch (RepositoryException e) 424 { 425 throw new AmetysRepositoryException("Error while getting cart elements", e); 426 } 427 428 return elmts; 429 } 430 431 /** 432 * Get the contents of the cart 433 * @return The elements of the cart 434 * @throws RepositoryException if an exception occurs while exploring the repository 435 */ 436 public List<ContentElement> getContentCartElements () throws RepositoryException 437 { 438 List<String> unexistingElmts = new ArrayList<>(); 439 440 List<ContentElement> elmts = new ArrayList<>(); 441 442 String[] contents = getValueOrDefault(CONTENT_CART_ELEMENTS, new String[0]); 443 444 for (String contentId : contents) 445 { 446 try 447 { 448 Content content = _getFactory().getResolver().resolveById(contentId); 449 elmts.add(new ContentElement(content, _getFactory()._getContentTypesHelper(), _getFactory()._getContentTypeEP())); 450 } 451 catch (UnknownAmetysObjectException e) 452 { 453 _logger.error("The content of id '{}' does not exist anymore. It will be deleting from cart '{}'.", contentId, getId()); 454 unexistingElmts.add(contentId); 455 } 456 } 457 // Delete unexisting contents 458 for (String contentId : unexistingElmts) 459 { 460 _removeContent(contentId); 461 } 462 463 return elmts; 464 } 465 466 /** 467 * Get the resources of the cart 468 * @return The elements of the cart 469 * @throws RepositoryException if an exception occurs while exploring the repository 470 */ 471 public List<ResourceElement> getResourceCartElements () throws RepositoryException 472 { 473 List<String> unexistingElmts = new ArrayList<>(); 474 List<ResourceElement> elmts = new ArrayList<>(); 475 476 477 String[] resources = getValueOrDefault(RESOURCE_CART_ELEMENTS, new String[0]); 478 479 for (String resourceId : resources) 480 { 481 try 482 { 483 Resource resource = _getFactory().getResolver().resolveById(resourceId); 484 elmts.add(new ResourceElement(resource)); 485 } 486 catch (UnknownAmetysObjectException e) 487 { 488 _logger.error("The resource of id '{}' does not exist anymore. It will be deleting from cart '{}'.", resourceId, getId()); 489 unexistingElmts.add(resourceId); 490 } 491 } 492 493 // Delete unexisting resources 494 for (String resourceId : unexistingElmts) 495 { 496 _removeResource(resourceId); 497 } 498 499 return elmts; 500 } 501 502 /** 503 * Get the resources of the cart 504 * @return The elements of the cart 505 * @throws RepositoryException if an exception occurs while exploring the repository 506 */ 507 public List<QueryFromDirectoryElement> getQueryFromDirectoryCartElements () throws RepositoryException 508 { 509 List<String> unexistingElmts = new ArrayList<>(); 510 List<QueryFromDirectoryElement> elmts = new ArrayList<>(); 511 512 513 String[] queries = getValueOrDefault(QUERIES_FROM_DIRECTORY_CART_ELEMENTS, new String[0]); 514 for (String queryId : queries) 515 { 516 try 517 { 518 Query query = _getFactory().getResolver().resolveById(queryId); 519 elmts.add(new QueryFromDirectoryElement(query)); 520 } 521 catch (UnknownAmetysObjectException e) 522 { 523 _logger.error("The query of id '{}' does not exist anymore. It will be deleting from cart '{}'.", queryId, getId()); 524 unexistingElmts.add(queryId); 525 } 526 } 527 528 // Delete unexisting queries 529 for (String queryId : unexistingElmts) 530 { 531 _removeQueryFromDirectory(queryId); 532 } 533 534 return elmts; 535 } 536 537 /** 538 * <code>true</code> if the query cart element exist 539 * @param queryId the query id 540 * @return <code>true</code> if the query cart element exist 541 */ 542 public boolean hasQueryFromDirectoryCartElement(String queryId) 543 { 544 String[] queries = getValueOrDefault(QUERIES_FROM_DIRECTORY_CART_ELEMENTS, new String[0]); 545 return ArrayUtils.contains(queries, queryId); 546 } 547 548 /** 549 * Get the queries of the cart 550 * @return The elements of the cart 551 * @throws RepositoryException if an exception occurs while exploring the repository 552 */ 553 public List<QueryElement> getQueryCartElements () throws RepositoryException 554 { 555 ModifiableRepeater queries = getRepeater(QUERIES_CART_ELEMENTS, true); 556 557 List<QueryElement> elmts = queries.getEntries() 558 .stream() 559 .map(entry -> { 560 String id = entry.getValue(QUERY_ID_PROPERTY); 561 UserIdentity author = entry.getValue(QUERY_AUTHOR_PROPERTY); 562 String query = entry.getValue(QUERY_DESCRIPTION_PROPERTY); 563 String title = entry.getValue(QUERY_TITLE_PROPERTY); 564 ZonedDateTime creationDate = entry.getValue(QUERY_DATE_PROPERTY); 565 566 return new QueryElement(id, query, author, creationDate, author, creationDate, title); 567 }) 568 .collect(Collectors.toList()); 569 570 return elmts; 571 } 572}