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