-Allow user to declare a public folder i)a checkbox named [Public] added in the web...
[pithos] / src / gr / ebs / gss / server / domain / Folder.java
1 /*\r
2  * Copyright 2007, 2008, 2009 Electronic Business Systems Ltd.\r
3  *\r
4  * This file is part of GSS.\r
5  *\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
10  *\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
15  *\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
18  */\r
19 package gr.ebs.gss.server.domain;\r
20 \r
21 import gr.ebs.gss.server.domain.dto.FolderDTO;\r
22 \r
23 import java.io.Serializable;\r
24 import java.io.UnsupportedEncodingException;\r
25 import java.net.URLEncoder;\r
26 import java.util.ArrayList;\r
27 import java.util.HashSet;\r
28 import java.util.List;\r
29 import java.util.Set;\r
30 \r
31 import javax.persistence.CascadeType;\r
32 import javax.persistence.Column;\r
33 import javax.persistence.Embedded;\r
34 import javax.persistence.Entity;\r
35 import javax.persistence.GeneratedValue;\r
36 import javax.persistence.Id;\r
37 import javax.persistence.JoinColumn;\r
38 import javax.persistence.ManyToOne;\r
39 import javax.persistence.OneToMany;\r
40 import javax.persistence.OrderBy;\r
41 import javax.persistence.Version;\r
42 \r
43 import org.hibernate.annotations.Cache;\r
44 import org.hibernate.annotations.CacheConcurrencyStrategy;\r
45 \r
46 /**\r
47  * The structure of a folder on the GSS service.\r
48  */\r
49 @Entity\r
50 @Cache(usage=CacheConcurrencyStrategy.READ_WRITE)\r
51 public final class Folder  implements Serializable{\r
52 \r
53         /**\r
54          * The persistence ID of the object.\r
55          */\r
56         @Id\r
57         @GeneratedValue\r
58         private Long id;\r
59 \r
60         /**\r
61          * Version field for optimistic locking.\r
62          */\r
63         @SuppressWarnings("unused")\r
64         @Version\r
65         private int version;\r
66 \r
67         /**\r
68          * The audit information.\r
69          */\r
70         @Embedded\r
71         private AuditInfo auditInfo;\r
72 \r
73         /**\r
74          * The icon filename.\r
75          */\r
76         private String icon;\r
77 \r
78         /**\r
79          * The folder name.\r
80          */\r
81         private String name;\r
82 \r
83         /**\r
84          * The files in this folder. A List so we can keep order.\r
85          */\r
86         @OneToMany(cascade = CascadeType.ALL, mappedBy = "folder")\r
87         @OrderBy("name")\r
88         private List<FileHeader> files=new ArrayList<FileHeader>();\r
89 \r
90         /**\r
91          * The subfolders in this folder. A List so we can keep order.\r
92          */\r
93         @OneToMany(cascade = CascadeType.ALL, mappedBy = "parent")\r
94         @OrderBy("name")\r
95         private List<Folder> subfolders=new ArrayList<Folder>();\r
96 \r
97         /**\r
98          * The parent folder of this one.\r
99          */\r
100         @ManyToOne\r
101         private Folder parent;\r
102 \r
103         /**\r
104          * The owner of this folder.\r
105          */\r
106         @ManyToOne(optional=false)\r
107         @JoinColumn(nullable=false)\r
108         private User owner;\r
109 \r
110         /**\r
111          * Set of Permission objects: The permissions (User and Group) for this\r
112          * Folder.\r
113          */\r
114         @OneToMany(cascade = CascadeType.ALL)\r
115         private Set<Permission> permissions = new HashSet<Permission>();\r
116 \r
117 \r
118         /**\r
119          * Is this folder temporarily deleted?\r
120          */\r
121         @Column(columnDefinition=" boolean DEFAULT false")\r
122         private boolean deleted=false;\r
123 \r
124         /**\r
125          * Can this folder be read by anyone?\r
126          * XXX: the columnDefinition is postgres specific, if deployment database is changed this shall be changed too\r
127          */\r
128         @Column(columnDefinition=" boolean DEFAULT false")\r
129         private boolean readForAll=false;\r
130 \r
131         /**\r
132          * Retrieve the ID.\r
133          *\r
134          * @return the ID\r
135          */\r
136         public Long getId() {\r
137                 return id;\r
138         }\r
139 \r
140         /**\r
141          * Retrieve the icon.\r
142          *\r
143          * @return the icon\r
144          */\r
145         public String getIcon() {\r
146                 return icon;\r
147         }\r
148 \r
149         /**\r
150          * Replace the icon.\r
151          *\r
152          * @param newIcon the new icon\r
153          */\r
154         public void setIcon(final String newIcon) {\r
155                 icon = newIcon;\r
156         }\r
157 \r
158         /**\r
159          * Retrieve the folder name.\r
160          *\r
161          * @return the name\r
162          */\r
163         public String getName() {\r
164                 return name;\r
165         }\r
166 \r
167         /**\r
168          * Modify the folder name.\r
169          *\r
170          * @param newName the new name\r
171          */\r
172         public void setName(final String newName) {\r
173                 name = newName;\r
174         }\r
175 \r
176         /**\r
177          * Retrieve the list of files in the folder.\r
178          *\r
179          * @return a list of file header objects\r
180          */\r
181         public List<FileHeader> getFiles() {\r
182                 return files;\r
183         }\r
184 \r
185         /**\r
186          * Replace the list of files in the folder.\r
187          *\r
188          * @param newFiles the new list of files\r
189          */\r
190         public void setFiles(final List<FileHeader> newFiles) {\r
191                 files = newFiles;\r
192         }\r
193 \r
194         /**\r
195          * Retrieve the list of subfolders.\r
196          *\r
197          * @return the subfolders\r
198          */\r
199         public List<Folder> getSubfolders() {\r
200                 return subfolders;\r
201         }\r
202 \r
203         /**\r
204          * Replace the list of subfolders.\r
205          *\r
206          * @param newSubfolders the new subfolders\r
207          */\r
208         public void setSubfolders(final List<Folder> newSubfolders) {\r
209                 subfolders = newSubfolders;\r
210         }\r
211 \r
212         /**\r
213          * Retrieve the parent folder.\r
214          *\r
215          * @return the parent\r
216          */\r
217         public Folder getParent() {\r
218                 return parent;\r
219         }\r
220 \r
221         /**\r
222          * Replace the parent folder.\r
223          *\r
224          * @param newParent the new parent\r
225          */\r
226         public void setParent(final Folder newParent) {\r
227                 parent = newParent;\r
228         }\r
229 \r
230         /**\r
231          * Retrieve the owner.\r
232          *\r
233          * @return the owner\r
234          */\r
235         public User getOwner() {\r
236                 return owner;\r
237         }\r
238 \r
239         /**\r
240          * Modify the owner.\r
241          *\r
242          * @param newOwner the new owner\r
243          */\r
244         public void setOwner(final User newOwner) {\r
245                 owner = newOwner;\r
246         }\r
247 \r
248         /**\r
249          * Retrieve the audit info.\r
250          *\r
251          * @return the audit info\r
252          */\r
253         public AuditInfo getAuditInfo() {\r
254                 return auditInfo;\r
255         }\r
256 \r
257         /**\r
258          * Modify the audit info.\r
259          *\r
260          * @param newAuditInfo the new audit info\r
261          */\r
262         public void setAuditInfo(final AuditInfo newAuditInfo) {\r
263                 auditInfo = newAuditInfo;\r
264         }\r
265 \r
266         /**\r
267          * Retrieve the permission set.\r
268          *\r
269          * @return the permissions\r
270          */\r
271         public Set<Permission> getPermissions() {\r
272                 return permissions;\r
273         }\r
274 \r
275         /**\r
276          * Replace the permission set.\r
277          *\r
278          * @param newPermissions the new permissions\r
279          */\r
280         public void setPermissions(final Set<Permission> newPermissions) {\r
281                 permissions = newPermissions;\r
282         }\r
283 \r
284         /**\r
285          * Adds a subfolder to this folder. If the child already belongs to another\r
286          * parent folder, it is first removed from it.\r
287          *\r
288          * @param subfolder Folder to add\r
289          * @throws IllegalArgumentException if folder is null\r
290          */\r
291         public void addSubfolder(final Folder subfolder) {\r
292                 if (subfolder == null)\r
293                         throw new IllegalArgumentException("Can't add a null subfolder as a child.");\r
294                 // Remove from old parent folder\r
295                 if (subfolder.getParent() != null)\r
296                         subfolder.getParent().removeSubfolder(subfolder);\r
297                 // Set parent in child\r
298                 subfolder.setParent(this);\r
299                 // Set child in parent\r
300                 getSubfolders().add(subfolder);\r
301         }\r
302 \r
303         /**\r
304          * Removes a subfolder from this folder.\r
305          *\r
306          * @param subfolder Folder to remove\r
307          * @throws IllegalArgumentException if subfolder is null\r
308          */\r
309         public void removeSubfolder(final Folder subfolder) {\r
310                 if (subfolder == null)\r
311                         throw new IllegalArgumentException("Can't remove a null subfolder.");\r
312                 getSubfolders().remove(subfolder);\r
313                 subfolder.setParent(null);\r
314         }\r
315 \r
316         /**\r
317          * Adds a file to this folder. If the file already belongs to another parent\r
318          * folder, it is first removed from it.\r
319          *\r
320          * @param file FileHeader to add\r
321          * @throws IllegalArgumentException if file is null\r
322          */\r
323         public void addFile(final FileHeader file) {\r
324                 if (file == null)\r
325                         throw new IllegalArgumentException("Can't add a null file.");\r
326                 // Remove from old parent folder\r
327                 if (file.getFolder() != null)\r
328                         file.getFolder().removeFile(file);\r
329 \r
330                 getFiles().add(file);\r
331                 file.setFolder(this);\r
332         }\r
333 \r
334         /**\r
335          * Removes a file from this folder.\r
336          *\r
337          * @param file FileHeader to remove\r
338          * @throws IllegalArgumentException if file is null\r
339          */\r
340         public void removeFile(final FileHeader file) {\r
341                 if (file == null)\r
342                         throw new IllegalArgumentException("Can't remove a null file.");\r
343                 getFiles().remove(file);\r
344                 file.setFolder(null);\r
345         }\r
346 \r
347         /**\r
348          * Adds a permission to this Folder.\r
349          *\r
350          * @param permission Permission to add\r
351          * @throws IllegalArgumentException if permission is null\r
352          */\r
353         public void addPermission(final Permission permission) {\r
354                 if (permission == null)\r
355                         throw new IllegalArgumentException("Can't add a null Permission.");\r
356                 getPermissions().add(permission);\r
357         }\r
358 \r
359         /**\r
360          * Return the FolderDTO for this Folder object. The object graph that is\r
361          * constructed has maximum depth 2. This method is mainly intended for use\r
362          * by the web application interface.\r
363          *\r
364          * @return the FolderDTO that corresponds to this Folder\r
365          */\r
366         public FolderDTO getDTO() {\r
367                 return getDTO(2);\r
368         }\r
369 \r
370         /**\r
371          * Return the FolderDTO for this Folder object. The object graph that is\r
372          * constructed has the specified maximum depth and contains marked as deleted folders\r
373          *\r
374          * @param depth the maximum depth of the returned folder tree\r
375          * @return the FolderDTO that corresponds to this Folder\r
376          */\r
377         private FolderDTO getDTO(int depth) {\r
378                 FolderDTO f = new FolderDTO();\r
379                 f.setId(id);\r
380                 f.setName(name);\r
381                 f.setPath(getPath());\r
382                 f.setOwner(owner.getDTO());\r
383                 f.setAuditInfo(auditInfo.getDTO());\r
384                 f.setDeleted(deleted);\r
385                 f.setReadForAll(readForAll);\r
386                 if (parent != null)\r
387                         f.setParent(parent.getDTO(0));\r
388                 for (Folder subfolder : subfolders)\r
389                         if (depth > 0)\r
390                                 f.getSubfolders().add(subfolder.getDTO(depth - 1));\r
391                 return f;\r
392         }\r
393 \r
394         /**\r
395          * Checks if the specified user has permission to delete this folder, by\r
396          * checking if the user has write permission to the parent folder.\r
397          *\r
398          * @param user the specified User\r
399          * @return true if the user has permission to delete the folder, false\r
400          *         otherwise\r
401          */\r
402         public boolean hasDeletePermission(final User user) {\r
403                 if (parent.hasWritePermission(user))\r
404                         return true;\r
405                 return false;\r
406         }\r
407 \r
408         /**\r
409          * Checks if the specified user has permission to modify this folder.\r
410          *\r
411          * @param user the specified User\r
412          * @return true if the user has permission to modify the folder, false\r
413          *         otherwise\r
414          */\r
415         public boolean hasWritePermission(final User user) {\r
416                 for (final Permission p : permissions)\r
417                         if (p.getUser() != null) {\r
418                                 if (p.getUser().equals(user) && p.getWrite())\r
419                                         return true;\r
420                         } else if (p.getGroup().contains(user) && p.getWrite())\r
421                                 return true;\r
422                 return false;\r
423         }\r
424 \r
425         /**\r
426          * Checks if the specified user has permission to read this folder.\r
427          *\r
428          * @param user the specified User\r
429          * @return true if the user has permission to read the folder, false\r
430          *         otherwise\r
431          */\r
432         public boolean hasReadPermission(final User user) {\r
433                 for (final Permission p : permissions)\r
434                         if (p.getUser() != null) {\r
435                                 if (p.getUser().equals(user) && p.getRead())\r
436                                         return true;\r
437                         } else if (p.getGroup().contains(user) && p.getRead())\r
438                                 return true;\r
439                 return false;\r
440         }\r
441 \r
442         /**\r
443          * Checks if the specified user has permission to modify the ACL of this file.\r
444          *\r
445          * @param user the specified User\r
446          * @return true if the user has permission to modify the ACL of the file, false\r
447          *         otherwise\r
448          */\r
449         public boolean hasModifyACLPermission(final User user) {\r
450                 for (final Permission p : permissions)\r
451                         if (p.getUser() != null) {\r
452                                 if (p.getUser().equals(user) && p.getModifyACL())\r
453                                         return true;\r
454                         } else if (p.getGroup().contains(user) && p.getModifyACL())\r
455                                 return true;\r
456                 return false;\r
457         }\r
458 \r
459         /**\r
460          * Checks if the specified folder is shared (if it has permissions for other users and groups)\r
461          *\r
462          * @param user the specified User\r
463          * @return true if the user has permission to read the folder, false\r
464          *         otherwise\r
465          */\r
466         public boolean isShared(final User user) {\r
467                 for (final Permission p : permissions)\r
468                         if (p.getUser() != null) {\r
469                                 if (!p.getUser().equals(user))\r
470                                         return true;\r
471                         } else if (!p.getGroup().contains(user))\r
472                                 return true;\r
473                 return false;\r
474         }\r
475 \r
476         public boolean isSharedForOtherUser(final User user) {\r
477                 for (final Permission p : permissions)\r
478                         if (p.getUser() != null) {\r
479                                 if (p.getUser().equals(user))\r
480                                         return true;\r
481                         } else if (p.getGroup().contains(user))\r
482                                 return true;\r
483                 return false;\r
484         }\r
485 \r
486 \r
487         /**\r
488          * Retrieve the deleted.\r
489          *\r
490          * @return the deleted\r
491          */\r
492         public boolean isDeleted() {\r
493                 return deleted;\r
494         }\r
495 \r
496 \r
497         /**\r
498          * Modify the deleted.\r
499          *\r
500          * @param newDeleted the deleted to set\r
501          */\r
502         public void setDeleted(boolean newDeleted) {\r
503                 deleted = newDeleted;\r
504         }\r
505 \r
506         /**\r
507          * Retrieve the full path of the folder, URL-encoded in the form:\r
508          * /parent1/parent2/parent3/name\r
509          *\r
510          * @return the full path from the root of the files namespace\r
511          */\r
512         public String getPath() {\r
513                 if (parent == null)\r
514                         return "/";\r
515                 try {\r
516                         return parent.getPath() + URLEncoder.encode(name, "UTF-8") + '/';\r
517                 } catch (UnsupportedEncodingException e) {\r
518                         throw new RuntimeException(e);\r
519                 }\r
520         }\r
521 \r
522         /**\r
523          * Modify the readForAll.\r
524          *\r
525          * @param newReadForAll the readForAll to set\r
526          */\r
527         public void setReadForAll(boolean newReadForAll) {\r
528                 readForAll = newReadForAll;\r
529         }\r
530 \r
531         /**\r
532          * Retrieve the readForAll.\r
533          *\r
534          * @return the readForAll\r
535          */\r
536         public boolean isReadForAll() {\r
537                 return readForAll;\r
538         }\r
539 \r
540 }\r