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