Statistics
| Branch: | Tag: | Revision:

root / src / org / gss_project / gss / server / domain / Folder.java @ 1206:292dec4eae08

History | View | Annotate | Download (13.8 kB)

1
/*
2
 * Copyright 2007, 2008, 2009 Electronic Business Systems Ltd.
3
 *
4
 * This file is part of GSS.
5
 *
6
 * GSS is free software: you can redistribute it and/or modify
7
 * it under the terms of the GNU General Public License as published by
8
 * the Free Software Foundation, either version 3 of the License, or
9
 * (at your option) any later version.
10
 *
11
 * GSS is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU General Public License
17
 * along with GSS.  If not, see <http://www.gnu.org/licenses/>.
18
 */
19
package org.gss_project.gss.server.domain;
20

    
21
import org.gss_project.gss.common.dto.FolderDTO;
22

    
23
import java.io.Serializable;
24
import java.io.UnsupportedEncodingException;
25
import java.net.URLEncoder;
26
import java.util.ArrayList;
27
import java.util.HashSet;
28
import java.util.List;
29
import java.util.Set;
30

    
31
import javax.persistence.CascadeType;
32
import javax.persistence.Column;
33
import javax.persistence.Embedded;
34
import javax.persistence.Entity;
35
import javax.persistence.GeneratedValue;
36
import javax.persistence.Id;
37
import javax.persistence.JoinColumn;
38
import javax.persistence.ManyToOne;
39
import javax.persistence.OneToMany;
40
import javax.persistence.OrderBy;
41
import javax.persistence.PrePersist;
42
import javax.persistence.PreUpdate;
43
import javax.persistence.Version;
44

    
45
import org.hibernate.annotations.Cache;
46
import org.hibernate.annotations.CacheConcurrencyStrategy;
47

    
48
/**
49
 * The structure of a folder on the GSS service.
50
 */
51
@Entity
52
@Cache(usage=CacheConcurrencyStrategy.READ_WRITE)
53
public final class Folder  implements Serializable{
54

    
55
        /**
56
         * The persistence ID of the object.
57
         */
58
        @Id
59
        @GeneratedValue
60
        private Long id;
61

    
62
        /**
63
         * Version field for optimistic locking.
64
         */
65
        @SuppressWarnings("unused")
66
        @Version
67
        private int version;
68

    
69
        /**
70
         * The audit information.
71
         */
72
        @Embedded
73
        private AuditInfo auditInfo;
74

    
75
        /**
76
         * The icon filename.
77
         */
78
        private String icon;
79

    
80
        /**
81
         * The folder name.
82
         */
83
        private String name;
84

    
85
        /**
86
         * The files in this folder. A List so we can keep order.
87
         */
88
        @OneToMany(cascade = CascadeType.ALL, mappedBy = "folder")
89
        @OrderBy("name")
90
        private List<FileHeader> files=new ArrayList<FileHeader>();
91

    
92
        /**
93
         * The subfolders in this folder. A List so we can keep order.
94
         */
95
        @OneToMany(cascade = CascadeType.ALL, mappedBy = "parent")
96
        @OrderBy("name")
97
        private List<Folder> subfolders=new ArrayList<Folder>();
98

    
99
        /**
100
         * The parent folder of this one.
101
         */
102
        @ManyToOne
103
        private Folder parent;
104

    
105
        /**
106
         * The owner of this folder.
107
         */
108
        @ManyToOne(optional=false)
109
        @JoinColumn(nullable=false)
110
        private User owner;
111

    
112
        /**
113
         * Set of Permission objects: The permissions (User and Group) for this
114
         * Folder.
115
         */
116
        @OneToMany(cascade = CascadeType.ALL)
117
        private Set<Permission> permissions = new HashSet<Permission>();
118

    
119

    
120
        /**
121
         * Is this folder temporarily deleted?
122
         */
123
        @Column(columnDefinition=" boolean DEFAULT false")
124
        private boolean deleted=false;
125

    
126
        /**
127
         * Can this folder be read by anyone?
128
         * XXX: the columnDefinition is postgres specific, if deployment database is changed this shall be changed too
129
         */
130
        @Column(columnDefinition=" boolean DEFAULT false")
131
        private boolean readForAll=false;
132
        
133
        @Column(columnDefinition=" boolean DEFAULT false")
134
        private Boolean shared;
135

    
136
        /**
137
         * Retrieve the ID.
138
         *
139
         * @return the ID
140
         */
141
        public Long getId() {
142
                return id;
143
        }
144

    
145
        /**
146
         * Retrieve the icon.
147
         *
148
         * @return the icon
149
         */
150
        public String getIcon() {
151
                return icon;
152
        }
153

    
154
        /**
155
         * Replace the icon.
156
         *
157
         * @param newIcon the new icon
158
         */
159
        public void setIcon(final String newIcon) {
160
                icon = newIcon;
161
        }
162

    
163
        /**
164
         * Retrieve the folder name.
165
         *
166
         * @return the name
167
         */
168
        public String getName() {
169
                return name;
170
        }
171

    
172
        /**
173
         * Modify the folder name.
174
         *
175
         * @param newName the new name
176
         */
177
        public void setName(final String newName) {
178
                name = newName;
179
        }
180

    
181
        /**
182
         * Retrieve the list of files in the folder.
183
         *
184
         * @return a list of file header objects
185
         */
186
        public List<FileHeader> getFiles() {
187
                return files;
188
        }
189

    
190
        /**
191
         * Replace the list of files in the folder.
192
         *
193
         * @param newFiles the new list of files
194
         */
195
        public void setFiles(final List<FileHeader> newFiles) {
196
                files = newFiles;
197
        }
198

    
199
        /**
200
         * Retrieve the list of subfolders.
201
         *
202
         * @return the subfolders
203
         */
204
        public List<Folder> getSubfolders() {
205
                return subfolders;
206
        }
207

    
208
        /**
209
         * Replace the list of subfolders.
210
         *
211
         * @param newSubfolders the new subfolders
212
         */
213
        public void setSubfolders(final List<Folder> newSubfolders) {
214
                subfolders = newSubfolders;
215
        }
216

    
217
        /**
218
         * Retrieve the parent folder.
219
         *
220
         * @return the parent
221
         */
222
        public Folder getParent() {
223
                return parent;
224
        }
225

    
226
        /**
227
         * Replace the parent folder.
228
         *
229
         * @param newParent the new parent
230
         */
231
        public void setParent(final Folder newParent) {
232
                parent = newParent;
233
        }
234

    
235
        /**
236
         * Retrieve the owner.
237
         *
238
         * @return the owner
239
         */
240
        public User getOwner() {
241
                return owner;
242
        }
243

    
244
        /**
245
         * Modify the owner.
246
         *
247
         * @param newOwner the new owner
248
         */
249
        public void setOwner(final User newOwner) {
250
                owner = newOwner;
251
        }
252

    
253
        /**
254
         * Retrieve the audit info.
255
         *
256
         * @return the audit info
257
         */
258
        public AuditInfo getAuditInfo() {
259
                return auditInfo;
260
        }
261

    
262
        /**
263
         * Modify the audit info.
264
         *
265
         * @param newAuditInfo the new audit info
266
         */
267
        public void setAuditInfo(final AuditInfo newAuditInfo) {
268
                auditInfo = newAuditInfo;
269
        }
270

    
271
        /**
272
         * Retrieve the permission set.
273
         *
274
         * @return the permissions
275
         */
276
        public Set<Permission> getPermissions() {
277
                return permissions;
278
        }
279

    
280
        /**
281
         * Replace the permission set.
282
         *
283
         * @param newPermissions the new permissions
284
         */
285
        public void setPermissions(final Set<Permission> newPermissions) {
286
                permissions = newPermissions;
287
        }
288

    
289
        /**
290
         * Adds a subfolder to this folder. If the child already belongs to another
291
         * parent folder, it is first removed from it.
292
         *
293
         * @param subfolder Folder to add
294
         * @throws IllegalArgumentException if folder is null
295
         */
296
        public void addSubfolder(final Folder subfolder) {
297
                if (subfolder == null)
298
                        throw new IllegalArgumentException("Can't add a null subfolder as a child.");
299
                // Remove from old parent folder
300
                if (subfolder.getParent() != null)
301
                        subfolder.getParent().removeSubfolder(subfolder);
302
                // Set parent in child
303
                subfolder.setParent(this);
304
                // Set child in parent
305
                getSubfolders().add(subfolder);
306
        }
307

    
308
        /**
309
         * Removes a subfolder from this folder.
310
         *
311
         * @param subfolder Folder to remove
312
         * @throws IllegalArgumentException if subfolder is null
313
         */
314
        public void removeSubfolder(final Folder subfolder) {
315
                if (subfolder == null)
316
                        throw new IllegalArgumentException("Can't remove a null subfolder.");
317
                getSubfolders().remove(subfolder);
318
                subfolder.setParent(null);
319
        }
320

    
321
        /**
322
         * Adds a file to this folder. If the file already belongs to another parent
323
         * folder, it is first removed from it.
324
         *
325
         * @param file FileHeader to add
326
         * @throws IllegalArgumentException if file is null
327
         */
328
        public void addFile(final FileHeader file) {
329
                if (file == null)
330
                        throw new IllegalArgumentException("Can't add a null file.");
331
                // Remove from old parent folder
332
                if (file.getFolder() != null)
333
                        file.getFolder().removeFile(file);
334

    
335
                getFiles().add(file);
336
                file.setFolder(this);
337
        }
338

    
339
        /**
340
         * Removes a file from this folder.
341
         *
342
         * @param file FileHeader to remove
343
         * @throws IllegalArgumentException if file is null
344
         */
345
        public void removeFile(final FileHeader file) {
346
                if (file == null)
347
                        throw new IllegalArgumentException("Can't remove a null file.");
348
                getFiles().remove(file);
349
                file.setFolder(null);
350
        }
351

    
352
        /**
353
         * Adds a permission to this Folder.
354
         *
355
         * @param permission Permission to add
356
         * @throws IllegalArgumentException if permission is null
357
         */
358
        public void addPermission(final Permission permission) {
359
                if (permission == null)
360
                        throw new IllegalArgumentException("Can't add a null Permission.");
361
                getPermissions().add(permission);
362
        }
363

    
364
        /**
365
         * Return the FolderDTO for this Folder object. The object graph that is
366
         * constructed has maximum depth 2. This method is mainly intended for use
367
         * by the web application interface.
368
         *
369
         * @return the FolderDTO that corresponds to this Folder
370
         */
371
        public FolderDTO getDTO() {
372
                return getDTO(2);
373
        }
374

    
375
        /**
376
         * Return the FolderDTO for this Folder object. The object graph that is
377
         * constructed has the specified maximum depth and contains marked as deleted folders
378
         *
379
         * @param depth the maximum depth of the returned folder tree
380
         * @return the FolderDTO that corresponds to this Folder
381
         */
382
        private FolderDTO getDTO(int depth) {
383
                FolderDTO f = new FolderDTO();
384
                f.setId(id);
385
                f.setName(name);
386
                f.setPath(getPath());
387
                f.setOwner(owner.getDTO());
388
                f.setAuditInfo(auditInfo.getDTO());
389
                f.setDeleted(deleted);
390
                f.setReadForAll(readForAll);
391
                f.setShared(getShared());
392
                if (parent != null)
393
                        f.setParent(parent.getDTO(0));
394
                for (Folder subfolder : subfolders)
395
                        if (depth > 0)
396
                                f.getSubfolders().add(subfolder.getDTO(depth - 1));
397
                return f;
398
        }
399

    
400
        /**
401
         * Checks if the specified user has permission to delete this folder, by
402
         * checking if the user has write permission to the parent folder.
403
         *
404
         * @param user the specified User
405
         * @return true if the user has permission to delete the folder, false
406
         *         otherwise
407
         */
408
        public boolean hasDeletePermission(final User user) {
409
                if (parent.hasWritePermission(user))
410
                        return true;
411
                return false;
412
        }
413

    
414
        /**
415
         * Checks if the specified user has permission to modify this folder.
416
         *
417
         * @param user the specified User
418
         * @return true if the user has permission to modify the folder, false
419
         *         otherwise
420
         */
421
        public boolean hasWritePermission(final User user) {
422
                for (final Permission p : permissions)
423
                        if (p.getUser() != null) {
424
                                if (p.getUser().equals(user) && p.getWrite())
425
                                        return true;
426
                        } else if (p.getGroup().contains(user) && p.getWrite())
427
                                return true;
428
                return false;
429
        }
430

    
431
        /**
432
         * Checks if the specified user has permission to read this folder.
433
         *
434
         * @param user the specified User
435
         * @return true if the user has permission to read the folder, false
436
         *         otherwise
437
         */
438
        public boolean hasReadPermission(final User user) {
439
                for (final Permission p : permissions)
440
                        if (p.getUser() != null) {
441
                                if (p.getUser().equals(user) && p.getRead())
442
                                        return true;
443
                        } else if (p.getGroup().contains(user) && p.getRead())
444
                                return true;
445
                return false;
446
        }
447

    
448
        /**
449
         * Checks if the specified user has permission to modify the ACL of this file.
450
         *
451
         * @param user the specified User
452
         * @return true if the user has permission to modify the ACL of the file, false
453
         *         otherwise
454
         */
455
        public boolean hasModifyACLPermission(final User user) {
456
                for (final Permission p : permissions)
457
                        if (p.getUser() != null) {
458
                                if (p.getUser().equals(user) && p.getModifyACL())
459
                                        return true;
460
                        } else if (p.getGroup().contains(user) && p.getModifyACL())
461
                                return true;
462
                return false;
463
        }
464

    
465
        /**
466
         * Checks if the specified folder is shared (if it has permissions for other users and groups)
467
         *
468
         * @param user the specified User
469
         * @return true if the user has permission to read the folder, false
470
         *         otherwise
471
         */
472
        public boolean isShared(final User user) {
473
                for (final Permission p : permissions)
474
                        if (p.getUser() != null) {
475
                                if (!p.getUser().equals(user))
476
                                        return true;
477
                        } else if (!p.getGroup().contains(user))
478
                                return true;
479
                return false;
480
        }
481

    
482
        public boolean isSharedForOtherUser(final User user) {
483
                for (final Permission p : permissions)
484
                        if (p.getUser() != null) {
485
                                if (p.getUser().equals(user))
486
                                        return true;
487
                        } else if (p.getGroup().contains(user))
488
                                return true;
489
                return false;
490
        }
491

    
492

    
493
        /**
494
         * Retrieve the deleted.
495
         *
496
         * @return the deleted
497
         */
498
        public boolean isDeleted() {
499
                return deleted;
500
        }
501

    
502

    
503
        /**
504
         * Modify the deleted.
505
         *
506
         * @param newDeleted the deleted to set
507
         */
508
        public void setDeleted(boolean newDeleted) {
509
                deleted = newDeleted;
510
        }
511

    
512
        /**
513
         * Retrieve the full path of the folder, URL-encoded in the form:
514
         * /parent1/parent2/parent3/name
515
         *
516
         * @return the full path from the root of the files namespace
517
         */
518
        public String getPath() {
519
                if (parent == null)
520
                        return "/";
521
                try {
522
                        return parent.getPath() + URLEncoder.encode(name, "UTF-8") + '/';
523
                } catch (UnsupportedEncodingException e) {
524
                        throw new RuntimeException(e);
525
                }
526
        }
527

    
528
        /**
529
         * Modify the readForAll.
530
         *
531
         * @param newReadForAll the readForAll to set
532
         */
533
        public void setReadForAll(boolean newReadForAll) {
534
                readForAll = newReadForAll;
535
        }
536

    
537
        /**
538
         * Retrieve the readForAll.
539
         *
540
         * @return the readForAll
541
         */
542
        public boolean isReadForAll() {
543
                return readForAll;
544
        }
545
        
546
        /**
547
         * Retrieve the shared.
548
         *
549
         * @return the shared
550
         */
551
        public Boolean getShared() {
552
                if(shared==null)
553
                        return false;
554
                return shared;
555
        }
556
        
557
        
558
        /**
559
         * Modify the shared.
560
         *
561
         * @param shared the shared to set
562
         */
563
        public void setShared(Boolean shared) {
564
                this.shared = shared;
565
        }
566
        
567
        @PrePersist
568
        @PreUpdate
569
        private void fixSharedFlag(){
570
                if(isReadForAll()||getPermissions().size()>1)
571
                        shared=true;
572
                else
573
                        shared=false;
574
        }
575

    
576
        /**
577
         * Retrieve the URI for this resource, relative to the REST API root URI.
578
         * This unique identifier can be used to refer to the resource from
579
         * various GSS clients.
580
         *
581
         * @return the URI
582
         */
583
        public String getURI() {
584
                return owner.getUsername() + FileHeader.PATH_FILES + getPath();
585
        }
586

    
587

    
588
}