2 * Copyright 2007, 2008, 2009 Electronic Business Systems Ltd.
\r
4 * This file is part of GSS.
\r
6 * GSS is free software: you can redistribute it and/or modify
\r
7 * it under the terms of the GNU General Public License as published by
\r
8 * the Free Software Foundation, either version 3 of the License, or
\r
9 * (at your option) any later version.
\r
11 * GSS is distributed in the hope that it will be useful,
\r
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
\r
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
\r
14 * GNU General Public License for more details.
\r
16 * You should have received a copy of the GNU General Public License
\r
17 * along with GSS. If not, see <http://www.gnu.org/licenses/>.
\r
19 package gr.ebs.gss.server.domain;
\r
21 import gr.ebs.gss.server.domain.dto.FileHeaderDTO;
\r
22 import gr.ebs.gss.server.domain.dto.FolderDTO;
\r
24 import java.io.Serializable;
\r
25 import java.io.UnsupportedEncodingException;
\r
26 import java.net.URLEncoder;
\r
27 import java.util.ArrayList;
\r
28 import java.util.HashSet;
\r
29 import java.util.List;
\r
30 import java.util.Set;
\r
32 import javax.persistence.CascadeType;
\r
33 import javax.persistence.Column;
\r
34 import javax.persistence.Embedded;
\r
35 import javax.persistence.Entity;
\r
36 import javax.persistence.GeneratedValue;
\r
37 import javax.persistence.Id;
\r
38 import javax.persistence.JoinColumn;
\r
39 import javax.persistence.ManyToOne;
\r
40 import javax.persistence.OneToMany;
\r
41 import javax.persistence.OrderBy;
\r
42 import javax.persistence.PrePersist;
\r
43 import javax.persistence.PreUpdate;
\r
44 import javax.persistence.Version;
\r
46 import org.hibernate.annotations.Cache;
\r
47 import org.hibernate.annotations.CacheConcurrencyStrategy;
\r
50 * The structure of a folder on the GSS service.
\r
53 @Cache(usage=CacheConcurrencyStrategy.READ_WRITE)
\r
54 public final class Folder implements Serializable{
\r
57 * The persistence ID of the object.
\r
64 * Version field for optimistic locking.
\r
66 @SuppressWarnings("unused")
\r
68 private int version;
\r
71 * The audit information.
\r
74 private AuditInfo auditInfo;
\r
77 * The icon filename.
\r
79 private String icon;
\r
84 private String name;
\r
87 * The files in this folder. A List so we can keep order.
\r
89 @OneToMany(cascade = CascadeType.ALL, mappedBy = "folder")
\r
91 private List<FileHeader> files=new ArrayList<FileHeader>();
\r
94 * The subfolders in this folder. A List so we can keep order.
\r
96 @OneToMany(cascade = CascadeType.ALL, mappedBy = "parent")
\r
98 private List<Folder> subfolders=new ArrayList<Folder>();
\r
101 * The parent folder of this one.
\r
104 private Folder parent;
\r
107 * The owner of this folder.
\r
109 @ManyToOne(optional=false)
\r
110 @JoinColumn(nullable=false)
\r
111 private User owner;
\r
114 * Set of Permission objects: The permissions (User and Group) for this
\r
117 @OneToMany(cascade = CascadeType.ALL)
\r
118 private Set<Permission> permissions = new HashSet<Permission>();
\r
122 * Is this folder temporarily deleted?
\r
124 @Column(columnDefinition=" boolean DEFAULT false")
\r
125 private boolean deleted=false;
\r
128 * Can this folder be read by anyone?
\r
129 * XXX: the columnDefinition is postgres specific, if deployment database is changed this shall be changed too
\r
131 @Column(columnDefinition=" boolean DEFAULT false")
\r
132 private boolean readForAll=false;
\r
134 @Column(columnDefinition=" boolean DEFAULT false")
\r
135 private Boolean shared;
\r
142 public Long getId() {
\r
147 * Retrieve the icon.
\r
151 public String getIcon() {
\r
156 * Replace the icon.
\r
158 * @param newIcon the new icon
\r
160 public void setIcon(final String newIcon) {
\r
165 * Retrieve the folder name.
\r
169 public String getName() {
\r
174 * Modify the folder name.
\r
176 * @param newName the new name
\r
178 public void setName(final String newName) {
\r
183 * Retrieve the list of files in the folder.
\r
185 * @return a list of file header objects
\r
187 public List<FileHeader> getFiles() {
\r
192 * Replace the list of files in the folder.
\r
194 * @param newFiles the new list of files
\r
196 public void setFiles(final List<FileHeader> newFiles) {
\r
201 * Retrieve the list of subfolders.
\r
203 * @return the subfolders
\r
205 public List<Folder> getSubfolders() {
\r
210 * Replace the list of subfolders.
\r
212 * @param newSubfolders the new subfolders
\r
214 public void setSubfolders(final List<Folder> newSubfolders) {
\r
215 subfolders = newSubfolders;
\r
219 * Retrieve the parent folder.
\r
221 * @return the parent
\r
223 public Folder getParent() {
\r
228 * Replace the parent folder.
\r
230 * @param newParent the new parent
\r
232 public void setParent(final Folder newParent) {
\r
233 parent = newParent;
\r
237 * Retrieve the owner.
\r
239 * @return the owner
\r
241 public User getOwner() {
\r
246 * Modify the owner.
\r
248 * @param newOwner the new owner
\r
250 public void setOwner(final User newOwner) {
\r
255 * Retrieve the audit info.
\r
257 * @return the audit info
\r
259 public AuditInfo getAuditInfo() {
\r
264 * Modify the audit info.
\r
266 * @param newAuditInfo the new audit info
\r
268 public void setAuditInfo(final AuditInfo newAuditInfo) {
\r
269 auditInfo = newAuditInfo;
\r
273 * Retrieve the permission set.
\r
275 * @return the permissions
\r
277 public Set<Permission> getPermissions() {
\r
278 return permissions;
\r
282 * Replace the permission set.
\r
284 * @param newPermissions the new permissions
\r
286 public void setPermissions(final Set<Permission> newPermissions) {
\r
287 permissions = newPermissions;
\r
291 * Adds a subfolder to this folder. If the child already belongs to another
\r
292 * parent folder, it is first removed from it.
\r
294 * @param subfolder Folder to add
\r
295 * @throws IllegalArgumentException if folder is null
\r
297 public void addSubfolder(final Folder subfolder) {
\r
298 if (subfolder == null)
\r
299 throw new IllegalArgumentException("Can't add a null subfolder as a child.");
\r
300 // Remove from old parent folder
\r
301 if (subfolder.getParent() != null)
\r
302 subfolder.getParent().removeSubfolder(subfolder);
\r
303 // Set parent in child
\r
304 subfolder.setParent(this);
\r
305 // Set child in parent
\r
306 getSubfolders().add(subfolder);
\r
310 * Removes a subfolder from this folder.
\r
312 * @param subfolder Folder to remove
\r
313 * @throws IllegalArgumentException if subfolder is null
\r
315 public void removeSubfolder(final Folder subfolder) {
\r
316 if (subfolder == null)
\r
317 throw new IllegalArgumentException("Can't remove a null subfolder.");
\r
318 getSubfolders().remove(subfolder);
\r
319 subfolder.setParent(null);
\r
323 * Adds a file to this folder. If the file already belongs to another parent
\r
324 * folder, it is first removed from it.
\r
326 * @param file FileHeader to add
\r
327 * @throws IllegalArgumentException if file is null
\r
329 public void addFile(final FileHeader file) {
\r
331 throw new IllegalArgumentException("Can't add a null file.");
\r
332 // Remove from old parent folder
\r
333 if (file.getFolder() != null)
\r
334 file.getFolder().removeFile(file);
\r
336 getFiles().add(file);
\r
337 file.setFolder(this);
\r
341 * Removes a file from this folder.
\r
343 * @param file FileHeader to remove
\r
344 * @throws IllegalArgumentException if file is null
\r
346 public void removeFile(final FileHeader file) {
\r
348 throw new IllegalArgumentException("Can't remove a null file.");
\r
349 getFiles().remove(file);
\r
350 file.setFolder(null);
\r
354 * Adds a permission to this Folder.
\r
356 * @param permission Permission to add
\r
357 * @throws IllegalArgumentException if permission is null
\r
359 public void addPermission(final Permission permission) {
\r
360 if (permission == null)
\r
361 throw new IllegalArgumentException("Can't add a null Permission.");
\r
362 getPermissions().add(permission);
\r
366 * Return the FolderDTO for this Folder object. The object graph that is
\r
367 * constructed has maximum depth 2. This method is mainly intended for use
\r
368 * by the web application interface.
\r
370 * @return the FolderDTO that corresponds to this Folder
\r
372 public FolderDTO getDTO() {
\r
377 * Return the FolderDTO for this Folder object. The object graph that is
\r
378 * constructed has the specified maximum depth and contains marked as deleted folders
\r
380 * @param depth the maximum depth of the returned folder tree
\r
381 * @return the FolderDTO that corresponds to this Folder
\r
383 private FolderDTO getDTO(int depth) {
\r
384 FolderDTO f = new FolderDTO();
\r
387 f.setPath(getPath());
\r
388 f.setOwner(owner.getDTO());
\r
389 f.setAuditInfo(auditInfo.getDTO());
\r
390 f.setDeleted(deleted);
\r
391 f.setReadForAll(readForAll);
\r
392 f.setShared(getShared());
\r
393 if (parent != null)
\r
394 f.setParent(parent.getDTO(0));
\r
395 for (Folder subfolder : subfolders)
\r
397 f.getSubfolders().add(subfolder.getDTO(depth - 1));
\r
402 * Checks if the specified user has permission to delete this folder, by
\r
403 * checking if the user has write permission to the parent folder.
\r
405 * @param user the specified User
\r
406 * @return true if the user has permission to delete the folder, false
\r
409 public boolean hasDeletePermission(final User user) {
\r
410 if (parent.hasWritePermission(user))
\r
416 * Checks if the specified user has permission to modify this folder.
\r
418 * @param user the specified User
\r
419 * @return true if the user has permission to modify the folder, false
\r
422 public boolean hasWritePermission(final User user) {
\r
423 for (final Permission p : permissions)
\r
424 if (p.getUser() != null) {
\r
425 if (p.getUser().equals(user) && p.getWrite())
\r
427 } else if (p.getGroup().contains(user) && p.getWrite())
\r
433 * Checks if the specified user has permission to read this folder.
\r
435 * @param user the specified User
\r
436 * @return true if the user has permission to read the folder, false
\r
439 public boolean hasReadPermission(final User user) {
\r
440 for (final Permission p : permissions)
\r
441 if (p.getUser() != null) {
\r
442 if (p.getUser().equals(user) && p.getRead())
\r
444 } else if (p.getGroup().contains(user) && p.getRead())
\r
450 * Checks if the specified user has permission to modify the ACL of this file.
\r
452 * @param user the specified User
\r
453 * @return true if the user has permission to modify the ACL of the file, false
\r
456 public boolean hasModifyACLPermission(final User user) {
\r
457 for (final Permission p : permissions)
\r
458 if (p.getUser() != null) {
\r
459 if (p.getUser().equals(user) && p.getModifyACL())
\r
461 } else if (p.getGroup().contains(user) && p.getModifyACL())
\r
467 * Checks if the specified folder is shared (if it has permissions for other users and groups)
\r
469 * @param user the specified User
\r
470 * @return true if the user has permission to read the folder, false
\r
473 public boolean isShared(final User user) {
\r
474 for (final Permission p : permissions)
\r
475 if (p.getUser() != null) {
\r
476 if (!p.getUser().equals(user))
\r
478 } else if (!p.getGroup().contains(user))
\r
483 public boolean isSharedForOtherUser(final User user) {
\r
484 for (final Permission p : permissions)
\r
485 if (p.getUser() != null) {
\r
486 if (p.getUser().equals(user))
\r
488 } else if (p.getGroup().contains(user))
\r
495 * Retrieve the deleted.
\r
497 * @return the deleted
\r
499 public boolean isDeleted() {
\r
505 * Modify the deleted.
\r
507 * @param newDeleted the deleted to set
\r
509 public void setDeleted(boolean newDeleted) {
\r
510 deleted = newDeleted;
\r
514 * Retrieve the full path of the folder, URL-encoded in the form:
\r
515 * /parent1/parent2/parent3/name
\r
517 * @return the full path from the root of the files namespace
\r
519 public String getPath() {
\r
520 if (parent == null)
\r
523 return parent.getPath() + URLEncoder.encode(name, "UTF-8") + '/';
\r
524 } catch (UnsupportedEncodingException e) {
\r
525 throw new RuntimeException(e);
\r
530 * Modify the readForAll.
\r
532 * @param newReadForAll the readForAll to set
\r
534 public void setReadForAll(boolean newReadForAll) {
\r
535 readForAll = newReadForAll;
\r
539 * Retrieve the readForAll.
\r
541 * @return the readForAll
\r
543 public boolean isReadForAll() {
\r
548 * Retrieve the shared.
\r
550 * @return the shared
\r
552 public Boolean getShared() {
\r
560 * Modify the shared.
\r
562 * @param shared the shared to set
\r
564 public void setShared(Boolean shared) {
\r
565 this.shared = shared;
\r
570 private void fixSharedFlag(){
\r
571 if(isReadForAll()||getPermissions().size()>1)
\r
578 * Retrieve the URI for this resource, relative to the REST API root URI.
\r
579 * This unique identifier can be used to refer to the resource from
\r
580 * various GSS clients.
\r
584 public String getURI() {
\r
585 return owner.getUsername() + FileHeader.PATH_FILES + getPath();
\r