Remove the redundant gss top-level directory.
[pithos] / src / gr / ebs / gss / server / domain / FileHeader.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.FileHeaderDTO;\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 /**\r
44  * The immutable part of the structure of a file on the GSS service.\r
45  */\r
46 @Entity\r
47 public final class FileHeader  implements Serializable{\r
48 \r
49         /**\r
50          * The persistence ID of the object.\r
51          */\r
52         @Id\r
53         @GeneratedValue\r
54         private Long id;\r
55 \r
56         /**\r
57          * Version field for optimistic locking.\r
58          */\r
59         @SuppressWarnings("unused")\r
60         @Version\r
61         private int version;\r
62 \r
63         /**\r
64          * The audit information.\r
65          */\r
66         @Embedded\r
67         private AuditInfo auditInfo;\r
68 \r
69         /**\r
70          * The icon filename.\r
71          */\r
72         private String icon;\r
73 \r
74         /**\r
75          * The file name.\r
76          */\r
77         private String name;\r
78 \r
79         /**\r
80          * The parent folder of this file.\r
81          */\r
82         @ManyToOne(optional=false)\r
83         @JoinColumn(nullable=false)\r
84         private Folder folder;\r
85 \r
86         /**\r
87          * Is this a versioned file?\r
88          */\r
89         private boolean versioned = false;\r
90         /**\r
91          * Is this file temporarily deleted?\r
92          * XXX: the columnDefinition is postgres specific, if deployment database is changed this shall be changed too\r
93          */\r
94         @Column(columnDefinition=" boolean DEFAULT false")\r
95         private boolean deleted=false;\r
96 \r
97         /**\r
98          * Can this file be read by anyone?\r
99          * XXX: the columnDefinition is postgres specific, if deployment database is changed this shall be changed too\r
100          */\r
101         @Column(columnDefinition=" boolean DEFAULT false")\r
102         private boolean readForAll=false;\r
103 \r
104         /**\r
105          * The owner of this file.\r
106          */\r
107         @ManyToOne(optional=false)\r
108         @JoinColumn(nullable=false)\r
109         private User owner;\r
110 \r
111         /**\r
112          * The bodies of this file. (A single one if not versioned.) A List so we\r
113          * can keep order.\r
114          */\r
115         @OneToMany(cascade = CascadeType.ALL, mappedBy = "header")\r
116         @OrderBy("version")\r
117         private List<FileBody> bodies;\r
118 \r
119         /**\r
120          * The current (most recent) body of this file. The single one if not\r
121          * versioned.\r
122          */\r
123         @ManyToOne\r
124         private FileBody currentBody;\r
125 \r
126         /**\r
127          * The list of all tags this file has specified from all Users.\r
128          */\r
129         @OneToMany(cascade = CascadeType.ALL, mappedBy = "file")\r
130         @OrderBy("tag")\r
131         private List<FileTag> fileTags = new ArrayList<FileTag>();\r
132 \r
133         /**\r
134          * Set of Permission objects: The permissions (User and Group) for this\r
135          * FileHeader.\r
136          */\r
137         @OneToMany(cascade = CascadeType.ALL)\r
138         private Set<Permission> permissions = new HashSet<Permission>();\r
139 \r
140         /**\r
141          * Retrieve the ID.\r
142          *\r
143          * @return the ID\r
144          */\r
145         public Long getId() {\r
146                 return id;\r
147         }\r
148 \r
149         /**\r
150          * Retrieve the icon.\r
151          *\r
152          * @return the icon\r
153          */\r
154         public String getIcon() {\r
155                 return icon;\r
156         }\r
157 \r
158         /**\r
159          * Modify the icon.\r
160          *\r
161          * @param newIcon the new icon\r
162          */\r
163         public void setIcon(final String newIcon) {\r
164                 icon = newIcon;\r
165         }\r
166 \r
167         /**\r
168          * Retrieve the name.\r
169          *\r
170          * @return the name\r
171          */\r
172         public String getName() {\r
173                 return name;\r
174         }\r
175 \r
176         /**\r
177          * Modify the name.\r
178          *\r
179          * @param newName the new name\r
180          */\r
181         public void setName(final String newName) {\r
182                 name = newName;\r
183         }\r
184 \r
185         /**\r
186          * Retrieve the folder.\r
187          *\r
188          * @return the folder object\r
189          */\r
190         public Folder getFolder() {\r
191                 return folder;\r
192         }\r
193 \r
194         /**\r
195          * Modify the folder.\r
196          *\r
197          * @param newFolder the new folder\r
198          */\r
199         public void setFolder(final Folder newFolder) {\r
200                 folder = newFolder;\r
201         }\r
202 \r
203         /**\r
204          * Determine whether this file is versioned or not.\r
205          *\r
206          * @return true if this file is versioned\r
207          */\r
208         public boolean isVersioned() {\r
209                 return versioned;\r
210         }\r
211 \r
212         /**\r
213          * Modify the versioning status of this file.\r
214          *\r
215          * @param newStatus the new versioning status\r
216          */\r
217         public void setVersioned(final boolean newStatus) {\r
218                 versioned = newStatus;\r
219         }\r
220 \r
221 \r
222         /**\r
223          * Is this file deleted or not?.\r
224          *\r
225          * @return the deleted\r
226          */\r
227         public boolean isDeleted() {\r
228                 return deleted;\r
229         }\r
230 \r
231 \r
232         /**\r
233          * Set whether this file is deleted .\r
234          *\r
235          * @param newDeleted the deletedFlag to set\r
236          */\r
237         public void setDeleted(boolean newDeleted) {\r
238                 deleted = newDeleted;\r
239         }\r
240 \r
241         /**\r
242          * Retrieve the owner.\r
243          *\r
244          * @return the owner\r
245          */\r
246         public User getOwner() {\r
247                 return owner;\r
248         }\r
249 \r
250         /**\r
251          *Modify the owner.\r
252          *\r
253          * @param newOwner the new owner\r
254          */\r
255         public void setOwner(final User newOwner) {\r
256                 owner = newOwner;\r
257         }\r
258 \r
259         /**\r
260          * Retrieve the list of bodies.\r
261          *\r
262          * @return the list of bodies\r
263          */\r
264         public List<FileBody> getBodies() {\r
265                 return bodies;\r
266         }\r
267 \r
268         /**\r
269          * Replace the list of bodies.\r
270          *\r
271          * @param newBodies the new list of bodies\r
272          */\r
273         public void setBodies(final List<FileBody> newBodies) {\r
274                 bodies = newBodies;\r
275         }\r
276 \r
277         /**\r
278          * Retrieve the current body.\r
279          *\r
280          * @return the current body\r
281          */\r
282         public FileBody getCurrentBody() {\r
283                 return currentBody;\r
284         }\r
285 \r
286         /**\r
287          * Set another body as the current one.\r
288          *\r
289          * @param newCurrentBody the new current body\r
290          */\r
291         public void setCurrentBody(final FileBody newCurrentBody) {\r
292                 currentBody = newCurrentBody;\r
293         }\r
294 \r
295         /**\r
296          * Retrieve the audit info.\r
297          *\r
298          * @return the audit info object\r
299          */\r
300         public AuditInfo getAuditInfo() {\r
301                 return auditInfo;\r
302         }\r
303 \r
304         /**\r
305          * Modify the audit info.\r
306          *\r
307          * @param newAuditInfo the new audit info\r
308          */\r
309         public void setAuditInfo(final AuditInfo newAuditInfo) {\r
310                 auditInfo = newAuditInfo;\r
311         }\r
312 \r
313         /**\r
314          * Retrieve the file tags.\r
315          *\r
316          * @return the list of file tags\r
317          */\r
318         public List<FileTag> getFileTags() {\r
319                 return fileTags;\r
320         }\r
321 \r
322         /**\r
323          * Replace the list of file tags.\r
324          *\r
325          * @param newFileTags the new file tags list\r
326          */\r
327         public void setFileTags(final List<FileTag> newFileTags) {\r
328                 fileTags = newFileTags;\r
329         }\r
330 \r
331         /**\r
332          * Retrieve the set of permissions.\r
333          *\r
334          * @return the permission set\r
335          */\r
336         public Set<Permission> getPermissions() {\r
337                 return permissions;\r
338         }\r
339 \r
340         /**\r
341          * Replace the permission set.\r
342          *\r
343          * @param newPermissions the new permission set\r
344          */\r
345         public void setPermissions(final Set<Permission> newPermissions) {\r
346                 permissions = newPermissions;\r
347         }\r
348 \r
349         /**\r
350          * Add a body to list of bodies.\r
351          *\r
352          * @param body InfoItemBody The body to add.\r
353          */\r
354         public void addBody(final FileBody body) {\r
355                 if (body == null)\r
356                         throw new IllegalArgumentException("Can't add a null FileBody.");\r
357                 // Remove from old header\r
358                 if (body.getHeader() != null)\r
359                         throw new IllegalArgumentException("Trying to add a FileBody that already belongs to a FileHeader.");\r
360 \r
361                 // Set parent in child\r
362                 body.setHeader(this);\r
363 \r
364                 // Update version number\r
365                 if (currentBody == null)\r
366                         body.setVersion(1);\r
367                 else\r
368                         body.setVersion(currentBody.getVersion() + 1);\r
369 \r
370                 currentBody = body;\r
371         }\r
372 \r
373 \r
374         /**\r
375          * Retrieve the readForAll.\r
376          *\r
377          * @return the readForAll\r
378          */\r
379         public boolean isReadForAll() {\r
380                 return readForAll;\r
381         }\r
382 \r
383 \r
384         /**\r
385          * Modify the readForAll.\r
386          *\r
387          * @param readForAll the readForAll to set\r
388          */\r
389         public void setReadForAll(boolean readForAll) {\r
390                 this.readForAll = readForAll;\r
391         }\r
392 \r
393         /**\r
394          * Returns current body version number formatted for display. Returns "-"\r
395          * for non-versioned file.\r
396          *\r
397          * @return the current version\r
398          */\r
399         public String getCurrentVersionString() {\r
400                 if (isVersioned())\r
401                         return String.valueOf(currentBody.getVersion());\r
402                 return "-";\r
403         }\r
404 \r
405         /**\r
406          * Adds a permission to this FileHeader.\r
407          *\r
408          * @param permission Permission to add\r
409          * @throws IllegalArgumentException if permission is null\r
410          */\r
411         public void addPermission(final Permission permission) {\r
412                 if (permission == null)\r
413                         throw new IllegalArgumentException("Can't add a null Permission.");\r
414                 getPermissions().add(permission);\r
415         }\r
416 \r
417         /**\r
418          * Constructs and returns a DTO for this instance for use by remote clients\r
419          *\r
420          * @return FileHeaderDTO\r
421          */\r
422         public FileHeaderDTO getDTO() {\r
423                 final FileHeaderDTO f = new FileHeaderDTO();\r
424                 f.setId(id);\r
425                 f.setName(name);\r
426                 f.setPath(getPath());\r
427                 f.setFolder(folder.getDTO());\r
428                 f.setVersioned(versioned);\r
429                 f.setVersion(currentBody.getVersion());\r
430                 f.setOwner(owner.getDTO());\r
431                 f.setFileSize(currentBody.getFileSize());\r
432                 f.setOriginalFilename(currentBody.getOriginalFilename());\r
433                 f.setOriginalFilenameEncoded(currentBody.getOriginalFilenameEncoded());\r
434                 f.setMimeType(currentBody.getMimeType());\r
435                 f.setDeleted(deleted);\r
436                 f.setReadForAll(readForAll);\r
437                 List<String> tags = new ArrayList<String>();\r
438                 for (FileTag tag : fileTags)\r
439                         tags.add(tag.getTag());\r
440                 f.setTags(tags);\r
441                 f.setAuditInfo(auditInfo.getDTO());\r
442                 return f;\r
443         }\r
444 \r
445         /**\r
446          * Checks if the specified user has permission to delete this file, by\r
447          * checking if the user has write permission to this object.\r
448          *\r
449          * @param user the specified User\r
450          * @return true if the user has permission to delete the file, false\r
451          *         otherwise\r
452          */\r
453         public boolean hasDeletePermission(final User user) {\r
454                 if (hasWritePermission(user))\r
455                         return true;\r
456                 return false;\r
457         }\r
458 \r
459         /**\r
460          * Checks if the specified user has permission to modify this file.\r
461          *\r
462          * @param user the specified User\r
463          * @return true if the user has permission to modify the file, false\r
464          *         otherwise\r
465          */\r
466         public boolean hasWritePermission(final User user) {\r
467                 for (final Permission p : permissions)\r
468                         if (p.getUser() != null) {\r
469                                 if (p.getUser().equals(user) && p.getWrite())\r
470                                         return true;\r
471                         } else if (p.getGroup().contains(user) && p.getWrite())\r
472                                 return true;\r
473                 return false;\r
474         }\r
475 \r
476         /**\r
477          * Checks if the specified user has permission to read this file.\r
478          *\r
479          * @param user the specified User\r
480          * @return true if the user has permission to read the file, false\r
481          *         otherwise\r
482          */\r
483         public boolean hasReadPermission(final User user) {\r
484                 if(readForAll)\r
485                         return true;\r
486                 for (final Permission p : permissions)\r
487                         if (p.getUser() != null) {\r
488                                 if (p.getUser().equals(user) && p.getRead())\r
489                                         return true;\r
490                         } else if (p.getGroup().contains(user) && p.getRead())\r
491                                 return true;\r
492                 return false;\r
493         }\r
494 \r
495         /**\r
496          * Checks if the specified user has permission to modify the ACL of this file.\r
497          *\r
498          * @param user the specified User\r
499          * @return true if the user has permission to modify the ACL of the file, false\r
500          *         otherwise\r
501          */\r
502         public boolean hasModifyACLPermission(final User user) {\r
503                 for (final Permission p : permissions)\r
504                         if (p.getUser() != null) {\r
505                                 if (p.getUser().equals(user) && p.getModifyACL())\r
506                                         return true;\r
507                         } else if (p.getGroup().contains(user) && p.getModifyACL())\r
508                                 return true;\r
509                 return false;\r
510         }\r
511 \r
512         /**\r
513          * Retrieve the full path of the file, URL-encoded in the form:\r
514          * /parent1/parent2/parent3/name\r
515          *\r
516          * @return the full path from the root of the files namespace\r
517          */\r
518         public String getPath() {\r
519                 try {\r
520                         return folder.getPath() + URLEncoder.encode(name, "UTF-8");\r
521                 } catch (UnsupportedEncodingException e) {\r
522                         throw new RuntimeException(e);\r
523                 }\r
524         }\r
525 }\r
526 \r