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