Add new attribute to OCFile to know if this file is shared with users/groups
[pub/Android/ownCloud.git] / src / com / owncloud / android / datamodel / OCFile.java
1 /**
2 * ownCloud Android client application
3 *
4 * Copyright (C) 2012 Bartek Przybylski
5 * Copyright (C) 2015 ownCloud Inc.
6 *
7 * This program is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2,
9 * as published by the Free Software Foundation.
10 *
11 * This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
18 *
19 */
20
21 package com.owncloud.android.datamodel;
22
23 import android.os.Parcel;
24 import android.os.Parcelable;
25 import android.webkit.MimeTypeMap;
26
27 import com.owncloud.android.lib.common.utils.Log_OC;
28
29 import java.io.File;
30
31 import third_parties.daveKoeller.AlphanumComparator;
32 public class OCFile implements Parcelable, Comparable<OCFile> {
33
34 public static final Parcelable.Creator<OCFile> CREATOR = new Parcelable.Creator<OCFile>() {
35 @Override
36 public OCFile createFromParcel(Parcel source) {
37 return new OCFile(source);
38 }
39
40 @Override
41 public OCFile[] newArray(int size) {
42 return new OCFile[size];
43 }
44 };
45
46 public static final String PATH_SEPARATOR = "/";
47 public static final String ROOT_PATH = PATH_SEPARATOR;
48
49 private static final String TAG = OCFile.class.getSimpleName();
50
51 private long mId;
52 private long mParentId;
53 private long mLength;
54 private long mCreationTimestamp;
55 private long mModifiedTimestamp;
56 private long mModifiedTimestampAtLastSyncForData;
57 private String mRemotePath;
58 private String mLocalPath;
59 private String mMimeType;
60 private boolean mNeedsUpdating;
61 private long mLastSyncDateForProperties;
62 private long mLastSyncDateForData;
63 private boolean mFavorite;
64
65 private String mEtag;
66
67 private boolean mShareByLink;
68 private String mPublicLink;
69
70 private String mPermissions;
71 private String mRemoteId;
72
73 private boolean mNeedsUpdateThumbnail;
74
75 private boolean mIsDownloading;
76
77 private String mEtagInConflict; // Save file etag in the server, when there is a conflict. No conflict = null
78
79 private boolean mShareWithUser;
80
81
82 /**
83 * Create new {@link OCFile} with given path.
84 * <p/>
85 * The path received must be URL-decoded. Path separator must be OCFile.PATH_SEPARATOR, and it must be the first character in 'path'.
86 *
87 * @param path The remote path of the file.
88 */
89 public OCFile(String path) {
90 resetData();
91 mNeedsUpdating = false;
92 if (path == null || path.length() <= 0 || !path.startsWith(PATH_SEPARATOR)) {
93 throw new IllegalArgumentException("Trying to create a OCFile with a non valid remote path: " + path);
94 }
95 mRemotePath = path;
96 }
97
98 /**
99 * Reconstruct from parcel
100 *
101 * @param source The source parcel
102 */
103 private OCFile(Parcel source) {
104 mId = source.readLong();
105 mParentId = source.readLong();
106 mLength = source.readLong();
107 mCreationTimestamp = source.readLong();
108 mModifiedTimestamp = source.readLong();
109 mModifiedTimestampAtLastSyncForData = source.readLong();
110 mRemotePath = source.readString();
111 mLocalPath = source.readString();
112 mMimeType = source.readString();
113 mNeedsUpdating = source.readInt() == 0;
114 mFavorite = source.readInt() == 1;
115 mLastSyncDateForProperties = source.readLong();
116 mLastSyncDateForData = source.readLong();
117 mEtag = source.readString();
118 mShareByLink = source.readInt() == 1;
119 mPublicLink = source.readString();
120 mPermissions = source.readString();
121 mRemoteId = source.readString();
122 mNeedsUpdateThumbnail = source.readInt() == 1;
123 mIsDownloading = source.readInt() == 1;
124 mEtagInConflict = source.readString();
125 mShareWithUser = source.readInt() == 1;
126
127 }
128
129 @Override
130 public void writeToParcel(Parcel dest, int flags) {
131 dest.writeLong(mId);
132 dest.writeLong(mParentId);
133 dest.writeLong(mLength);
134 dest.writeLong(mCreationTimestamp);
135 dest.writeLong(mModifiedTimestamp);
136 dest.writeLong(mModifiedTimestampAtLastSyncForData);
137 dest.writeString(mRemotePath);
138 dest.writeString(mLocalPath);
139 dest.writeString(mMimeType);
140 dest.writeInt(mNeedsUpdating ? 1 : 0);
141 dest.writeInt(mFavorite ? 1 : 0);
142 dest.writeLong(mLastSyncDateForProperties);
143 dest.writeLong(mLastSyncDateForData);
144 dest.writeString(mEtag);
145 dest.writeInt(mShareByLink ? 1 : 0);
146 dest.writeString(mPublicLink);
147 dest.writeString(mPermissions);
148 dest.writeString(mRemoteId);
149 dest.writeInt(mNeedsUpdateThumbnail ? 1 : 0);
150 dest.writeInt(mIsDownloading ? 1 : 0);
151 dest.writeString(mEtagInConflict);
152 dest.writeInt(mShareWithUser ? 1 : 0);
153 }
154
155 /**
156 * Gets the ID of the file
157 *
158 * @return the file ID
159 */
160 public long getFileId() {
161 return mId;
162 }
163
164 /**
165 * Returns the remote path of the file on ownCloud
166 *
167 * @return The remote path to the file
168 */
169 public String getRemotePath() {
170 return mRemotePath;
171 }
172
173 /**
174 * Can be used to check, whether or not this file exists in the database
175 * already
176 *
177 * @return true, if the file exists in the database
178 */
179 public boolean fileExists() {
180 return mId != -1;
181 }
182
183 /**
184 * Use this to find out if this file is a folder.
185 *
186 * @return true if it is a folder
187 */
188 public boolean isFolder() {
189 return mMimeType != null && mMimeType.equals("DIR");
190 }
191
192 /**
193 * Use this to check if this file is available locally
194 *
195 * @return true if it is
196 */
197 public boolean isDown() {
198 if (mLocalPath != null && mLocalPath.length() > 0) {
199 File file = new File(mLocalPath);
200 return (file.exists());
201 }
202 return false;
203 }
204
205 /**
206 * The path, where the file is stored locally
207 *
208 * @return The local path to the file
209 */
210 public String getStoragePath() {
211 return mLocalPath;
212 }
213
214 /**
215 * Can be used to set the path where the file is stored
216 *
217 * @param storage_path to set
218 */
219 public void setStoragePath(String storage_path) {
220 mLocalPath = storage_path;
221 }
222
223 /**
224 * Get a UNIX timestamp of the file creation time
225 *
226 * @return A UNIX timestamp of the time that file was created
227 */
228 public long getCreationTimestamp() {
229 return mCreationTimestamp;
230 }
231
232 /**
233 * Set a UNIX timestamp of the time the file was created
234 *
235 * @param creation_timestamp to set
236 */
237 public void setCreationTimestamp(long creation_timestamp) {
238 mCreationTimestamp = creation_timestamp;
239 }
240
241 /**
242 * Get a UNIX timestamp of the file modification time.
243 *
244 * @return A UNIX timestamp of the modification time, corresponding to the value returned by the server
245 * in the last synchronization of the properties of this file.
246 */
247 public long getModificationTimestamp() {
248 return mModifiedTimestamp;
249 }
250
251 /**
252 * Set a UNIX timestamp of the time the time the file was modified.
253 * <p/>
254 * To update with the value returned by the server in every synchronization of the properties
255 * of this file.
256 *
257 * @param modification_timestamp to set
258 */
259 public void setModificationTimestamp(long modification_timestamp) {
260 mModifiedTimestamp = modification_timestamp;
261 }
262
263
264 /**
265 * Get a UNIX timestamp of the file modification time.
266 *
267 * @return A UNIX timestamp of the modification time, corresponding to the value returned by the server
268 * in the last synchronization of THE CONTENTS of this file.
269 */
270 public long getModificationTimestampAtLastSyncForData() {
271 return mModifiedTimestampAtLastSyncForData;
272 }
273
274 /**
275 * Set a UNIX timestamp of the time the time the file was modified.
276 * <p/>
277 * To update with the value returned by the server in every synchronization of THE CONTENTS
278 * of this file.
279 *
280 * @param modificationTimestamp to set
281 */
282 public void setModificationTimestampAtLastSyncForData(long modificationTimestamp) {
283 mModifiedTimestampAtLastSyncForData = modificationTimestamp;
284 }
285
286
287 /**
288 * Returns the filename and "/" for the root directory
289 *
290 * @return The name of the file
291 */
292 public String getFileName() {
293 File f = new File(getRemotePath());
294 return f.getName().length() == 0 ? ROOT_PATH : f.getName();
295 }
296
297 /**
298 * Sets the name of the file
299 * <p/>
300 * Does nothing if the new name is null, empty or includes "/" ; or if the file is the root
301 * directory
302 */
303 public void setFileName(String name) {
304 Log_OC.d(TAG, "OCFile name changin from " + mRemotePath);
305 if (name != null && name.length() > 0 && !name.contains(PATH_SEPARATOR) &&
306 !mRemotePath.equals(ROOT_PATH)) {
307 String parent = (new File(getRemotePath())).getParent();
308 parent = (parent.endsWith(PATH_SEPARATOR)) ? parent : parent + PATH_SEPARATOR;
309 mRemotePath = parent + name;
310 if (isFolder()) {
311 mRemotePath += PATH_SEPARATOR;
312 }
313 Log_OC.d(TAG, "OCFile name changed to " + mRemotePath);
314 }
315 }
316
317 /**
318 * Can be used to get the Mimetype
319 *
320 * @return the Mimetype as a String
321 */
322 public String getMimetype() {
323 return mMimeType;
324 }
325
326 /**
327 * Used internally. Reset all file properties
328 */
329 private void resetData() {
330 mId = -1;
331 mRemotePath = null;
332 mParentId = 0;
333 mLocalPath = null;
334 mMimeType = null;
335 mLength = 0;
336 mCreationTimestamp = 0;
337 mModifiedTimestamp = 0;
338 mModifiedTimestampAtLastSyncForData = 0;
339 mLastSyncDateForProperties = 0;
340 mLastSyncDateForData = 0;
341 mFavorite = false;
342 mNeedsUpdating = false;
343 mEtag = null;
344 mShareByLink = false;
345 mPublicLink = null;
346 mPermissions = null;
347 mRemoteId = null;
348 mNeedsUpdateThumbnail = false;
349 mIsDownloading = false;
350 mEtagInConflict = null;
351 mShareWithUser = false;
352 }
353
354 /**
355 * Sets the ID of the file
356 *
357 * @param file_id to set
358 */
359 public void setFileId(long file_id) {
360 mId = file_id;
361 }
362
363 /**
364 * Sets the Mime-Type of the
365 *
366 * @param mimetype to set
367 */
368 public void setMimetype(String mimetype) {
369 mMimeType = mimetype;
370 }
371
372 /**
373 * Sets the ID of the parent folder
374 *
375 * @param parent_id to set
376 */
377 public void setParentId(long parent_id) {
378 mParentId = parent_id;
379 }
380
381 /**
382 * Sets the file size in bytes
383 *
384 * @param file_len to set
385 */
386 public void setFileLength(long file_len) {
387 mLength = file_len;
388 }
389
390 /**
391 * Returns the size of the file in bytes
392 *
393 * @return The filesize in bytes
394 */
395 public long getFileLength() {
396 return mLength;
397 }
398
399 /**
400 * Returns the ID of the parent Folder
401 *
402 * @return The ID
403 */
404 public long getParentId() {
405 return mParentId;
406 }
407
408 /**
409 * Check, if this file needs updating
410 *
411 * @return
412 */
413 public boolean needsUpdatingWhileSaving() {
414 return mNeedsUpdating;
415 }
416
417 public boolean needsUpdateThumbnail() {
418 return mNeedsUpdateThumbnail;
419 }
420
421 public void setNeedsUpdateThumbnail(boolean needsUpdateThumbnail) {
422 this.mNeedsUpdateThumbnail = needsUpdateThumbnail;
423 }
424
425 public long getLastSyncDateForProperties() {
426 return mLastSyncDateForProperties;
427 }
428
429 public void setLastSyncDateForProperties(long lastSyncDate) {
430 mLastSyncDateForProperties = lastSyncDate;
431 }
432
433 public long getLastSyncDateForData() {
434 return mLastSyncDateForData;
435 }
436
437 public void setLastSyncDateForData(long lastSyncDate) {
438 mLastSyncDateForData = lastSyncDate;
439 }
440
441 public void setFavorite(boolean favorite) {
442 mFavorite = favorite;
443 }
444
445 public boolean isFavorite() {
446 return mFavorite;
447 }
448
449 @Override
450 public int describeContents() {
451 return super.hashCode();
452 }
453
454 @Override
455 public int compareTo(OCFile another) {
456 if (isFolder() && another.isFolder()) {
457 return getRemotePath().toLowerCase().compareTo(another.getRemotePath().toLowerCase());
458 } else if (isFolder()) {
459 return -1;
460 } else if (another.isFolder()) {
461 return 1;
462 }
463 return new AlphanumComparator().compare(this, another);
464 }
465
466 @Override
467 public boolean equals(Object o) {
468 if (o instanceof OCFile) {
469 OCFile that = (OCFile) o;
470 if (that != null) {
471 return this.mId == that.mId;
472 }
473 }
474
475 return false;
476 }
477
478 @Override
479 public String toString() {
480 String asString = "[id=%s, name=%s, mime=%s, downloaded=%s, local=%s, remote=%s, " +
481 "parentId=%s, favorite=%s etag=%s]";
482 asString = String.format(asString, Long.valueOf(mId), getFileName(), mMimeType, isDown(),
483 mLocalPath, mRemotePath, Long.valueOf(mParentId), Boolean.valueOf(mFavorite),
484 mEtag);
485 return asString;
486 }
487
488 public String getEtag() {
489 return mEtag;
490 }
491
492 public void setEtag(String etag) {
493 this.mEtag = (etag != null ? etag : "");
494 }
495
496 public boolean isShareByLink() {
497 return mShareByLink;
498 }
499
500 public void setShareByLink(boolean shareByLink) {
501 this.mShareByLink = shareByLink;
502 }
503
504 public String getPublicLink() {
505 return mPublicLink;
506 }
507
508 public void setPublicLink(String publicLink) {
509 this.mPublicLink = publicLink;
510 }
511
512 public long getLocalModificationTimestamp() {
513 if (mLocalPath != null && mLocalPath.length() > 0) {
514 File f = new File(mLocalPath);
515 return f.lastModified();
516 }
517 return 0;
518 }
519
520 /**
521 * @return 'True' if the file contains audio
522 */
523 public boolean isAudio() {
524 return (mMimeType != null && mMimeType.startsWith("audio/"));
525 }
526
527 /**
528 * @return 'True' if the file contains video
529 */
530 public boolean isVideo() {
531 return (mMimeType != null && mMimeType.startsWith("video/"));
532 }
533
534 /**
535 * @return 'True' if the file contains an image
536 */
537 public boolean isImage() {
538 return ((mMimeType != null && mMimeType.startsWith("image/")) ||
539 getMimeTypeFromName().startsWith("image/"));
540 }
541
542 /**
543 * @return 'True' if the file is simple text (e.g. not application-dependent, like .doc or .docx)
544 */
545 public boolean isText() {
546 return ((mMimeType != null && mMimeType.startsWith("text/")) ||
547 getMimeTypeFromName().startsWith("text/"));
548 }
549
550 public String getMimeTypeFromName() {
551 String extension = "";
552 int pos = mRemotePath.lastIndexOf('.');
553 if (pos >= 0) {
554 extension = mRemotePath.substring(pos + 1);
555 }
556 String result = MimeTypeMap.getSingleton().
557 getMimeTypeFromExtension(extension.toLowerCase());
558 return (result != null) ? result : "";
559 }
560
561 /**
562 * @return 'True' if the file is hidden
563 */
564 public boolean isHidden() {
565 return getFileName().startsWith(".");
566 }
567
568 public String getPermissions() {
569 return mPermissions;
570 }
571
572 public void setPermissions(String permissions) {
573 this.mPermissions = permissions;
574 }
575
576 public String getRemoteId() {
577 return mRemoteId;
578 }
579
580 public void setRemoteId(String remoteId) {
581 this.mRemoteId = remoteId;
582 }
583
584 public boolean isDownloading() {
585 return mIsDownloading;
586 }
587
588 public void setDownloading(boolean isDownloading) {
589 this.mIsDownloading = isDownloading;
590 }
591
592 public String getEtagInConflict() {
593 return mEtagInConflict;
594 }
595
596 public void setEtagInConflict(String etagInConflict) {
597 mEtagInConflict = etagInConflict;
598 }
599
600 public boolean isShareWithUser() {
601 return mShareWithUser;
602 }
603
604 public void setShareWithUser(boolean shareWithUser) {
605 this.mShareWithUser = shareWithUser;
606 }
607
608 }