2 * ownCloud Android client application
4 * Copyright (C) 2012 Bartek Przybylski
5 * Copyright (C) 2015 ownCloud Inc.
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.
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.
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/>.
21 package com
.owncloud
.android
.datamodel
;
23 import android
.os
.Parcel
;
24 import android
.os
.Parcelable
;
25 import android
.webkit
.MimeTypeMap
;
27 import com
.owncloud
.android
.lib
.common
.utils
.Log_OC
;
31 import third_parties
.daveKoeller
.AlphanumComparator
;
32 public class OCFile
implements Parcelable
, Comparable
<OCFile
> {
34 public static final Parcelable
.Creator
<OCFile
> CREATOR
= new Parcelable
.Creator
<OCFile
>() {
36 public OCFile
createFromParcel(Parcel source
) {
37 return new OCFile(source
);
41 public OCFile
[] newArray(int size
) {
42 return new OCFile
[size
];
46 private final static String PERMISSION_SHARED_WITH_ME
= "S"; // TODO move to better location
48 public static final String PATH_SEPARATOR
= "/";
49 public static final String ROOT_PATH
= PATH_SEPARATOR
;
51 private static final String TAG
= OCFile
.class.getSimpleName();
54 private long mParentId
;
56 private long mCreationTimestamp
;
57 private long mModifiedTimestamp
;
58 private long mModifiedTimestampAtLastSyncForData
;
59 private String mRemotePath
;
60 private String mLocalPath
;
61 private String mMimeType
;
62 private boolean mNeedsUpdating
;
63 private long mLastSyncDateForProperties
;
64 private long mLastSyncDateForData
;
65 private boolean mFavorite
;
69 private boolean mShareByLink
;
70 private String mPublicLink
;
72 private String mPermissions
;
73 private String mRemoteId
;
75 private boolean mNeedsUpdateThumbnail
;
77 private boolean mIsDownloading
;
79 private String mEtagInConflict
; // Save file etag in the server, when there is a conflict. No conflict = null
81 private boolean mShareWithUser
;
85 * Create new {@link OCFile} with given path.
87 * The path received must be URL-decoded. Path separator must be OCFile.PATH_SEPARATOR, and it must be the first character in 'path'.
89 * @param path The remote path of the file.
91 public OCFile(String path
) {
93 mNeedsUpdating
= false
;
94 if (path
== null
|| path
.length() <= 0 || !path
.startsWith(PATH_SEPARATOR
)) {
95 throw new IllegalArgumentException("Trying to create a OCFile with a non valid remote path: " + path
);
101 * Reconstruct from parcel
103 * @param source The source parcel
105 private OCFile(Parcel source
) {
106 mId
= source
.readLong();
107 mParentId
= source
.readLong();
108 mLength
= source
.readLong();
109 mCreationTimestamp
= source
.readLong();
110 mModifiedTimestamp
= source
.readLong();
111 mModifiedTimestampAtLastSyncForData
= source
.readLong();
112 mRemotePath
= source
.readString();
113 mLocalPath
= source
.readString();
114 mMimeType
= source
.readString();
115 mNeedsUpdating
= source
.readInt() == 0;
116 mFavorite
= source
.readInt() == 1;
117 mLastSyncDateForProperties
= source
.readLong();
118 mLastSyncDateForData
= source
.readLong();
119 mEtag
= source
.readString();
120 mShareByLink
= source
.readInt() == 1;
121 mPublicLink
= source
.readString();
122 mPermissions
= source
.readString();
123 mRemoteId
= source
.readString();
124 mNeedsUpdateThumbnail
= source
.readInt() == 1;
125 mIsDownloading
= source
.readInt() == 1;
126 mEtagInConflict
= source
.readString();
127 mShareWithUser
= source
.readInt() == 1;
132 public void writeToParcel(Parcel dest
, int flags
) {
134 dest
.writeLong(mParentId
);
135 dest
.writeLong(mLength
);
136 dest
.writeLong(mCreationTimestamp
);
137 dest
.writeLong(mModifiedTimestamp
);
138 dest
.writeLong(mModifiedTimestampAtLastSyncForData
);
139 dest
.writeString(mRemotePath
);
140 dest
.writeString(mLocalPath
);
141 dest
.writeString(mMimeType
);
142 dest
.writeInt(mNeedsUpdating ?
1 : 0);
143 dest
.writeInt(mFavorite ?
1 : 0);
144 dest
.writeLong(mLastSyncDateForProperties
);
145 dest
.writeLong(mLastSyncDateForData
);
146 dest
.writeString(mEtag
);
147 dest
.writeInt(mShareByLink ?
1 : 0);
148 dest
.writeString(mPublicLink
);
149 dest
.writeString(mPermissions
);
150 dest
.writeString(mRemoteId
);
151 dest
.writeInt(mNeedsUpdateThumbnail ?
1 : 0);
152 dest
.writeInt(mIsDownloading ?
1 : 0);
153 dest
.writeString(mEtagInConflict
);
154 dest
.writeInt(mShareWithUser ?
1 : 0);
158 * Gets the ID of the file
160 * @return the file ID
162 public long getFileId() {
167 * Returns the remote path of the file on ownCloud
169 * @return The remote path to the file
171 public String
getRemotePath() {
176 * Can be used to check, whether or not this file exists in the database
179 * @return true, if the file exists in the database
181 public boolean fileExists() {
186 * Use this to find out if this file is a folder.
188 * @return true if it is a folder
190 public boolean isFolder() {
191 return mMimeType
!= null
&& mMimeType
.equals("DIR");
195 * Use this to check if this file is available locally
197 * @return true if it is
199 public boolean isDown() {
200 if (mLocalPath
!= null
&& mLocalPath
.length() > 0) {
201 File file
= new File(mLocalPath
);
202 return (file
.exists());
208 * The path, where the file is stored locally
210 * @return The local path to the file
212 public String
getStoragePath() {
217 * Can be used to set the path where the file is stored
219 * @param storage_path to set
221 public void setStoragePath(String storage_path
) {
222 mLocalPath
= storage_path
;
226 * Get a UNIX timestamp of the file creation time
228 * @return A UNIX timestamp of the time that file was created
230 public long getCreationTimestamp() {
231 return mCreationTimestamp
;
235 * Set a UNIX timestamp of the time the file was created
237 * @param creation_timestamp to set
239 public void setCreationTimestamp(long creation_timestamp
) {
240 mCreationTimestamp
= creation_timestamp
;
244 * Get a UNIX timestamp of the file modification time.
246 * @return A UNIX timestamp of the modification time, corresponding to the value returned by the server
247 * in the last synchronization of the properties of this file.
249 public long getModificationTimestamp() {
250 return mModifiedTimestamp
;
254 * Set a UNIX timestamp of the time the time the file was modified.
256 * To update with the value returned by the server in every synchronization of the properties
259 * @param modification_timestamp to set
261 public void setModificationTimestamp(long modification_timestamp
) {
262 mModifiedTimestamp
= modification_timestamp
;
267 * Get a UNIX timestamp of the file modification time.
269 * @return A UNIX timestamp of the modification time, corresponding to the value returned by the server
270 * in the last synchronization of THE CONTENTS of this file.
272 public long getModificationTimestampAtLastSyncForData() {
273 return mModifiedTimestampAtLastSyncForData
;
277 * Set a UNIX timestamp of the time the time the file was modified.
279 * To update with the value returned by the server in every synchronization of THE CONTENTS
282 * @param modificationTimestamp to set
284 public void setModificationTimestampAtLastSyncForData(long modificationTimestamp
) {
285 mModifiedTimestampAtLastSyncForData
= modificationTimestamp
;
290 * Returns the filename and "/" for the root directory
292 * @return The name of the file
294 public String
getFileName() {
295 File f
= new File(getRemotePath());
296 return f
.getName().length() == 0 ? ROOT_PATH
: f
.getName();
300 * Sets the name of the file
302 * Does nothing if the new name is null, empty or includes "/" ; or if the file is the root
305 public void setFileName(String name
) {
306 Log_OC
.d(TAG
, "OCFile name changin from " + mRemotePath
);
307 if (name
!= null
&& name
.length() > 0 && !name
.contains(PATH_SEPARATOR
) &&
308 !mRemotePath
.equals(ROOT_PATH
)) {
309 String parent
= (new File(getRemotePath())).getParent();
310 parent
= (parent
.endsWith(PATH_SEPARATOR
)) ? parent
: parent
+ PATH_SEPARATOR
;
311 mRemotePath
= parent
+ name
;
313 mRemotePath
+= PATH_SEPARATOR
;
315 Log_OC
.d(TAG
, "OCFile name changed to " + mRemotePath
);
320 * Can be used to get the Mimetype
322 * @return the Mimetype as a String
324 public String
getMimetype() {
329 * Used internally. Reset all file properties
331 private void resetData() {
338 mCreationTimestamp
= 0;
339 mModifiedTimestamp
= 0;
340 mModifiedTimestampAtLastSyncForData
= 0;
341 mLastSyncDateForProperties
= 0;
342 mLastSyncDateForData
= 0;
344 mNeedsUpdating
= false
;
346 mShareByLink
= false
;
350 mNeedsUpdateThumbnail
= false
;
351 mIsDownloading
= false
;
352 mEtagInConflict
= null
;
353 mShareWithUser
= false
;
357 * Sets the ID of the file
359 * @param file_id to set
361 public void setFileId(long file_id
) {
366 * Sets the Mime-Type of the
368 * @param mimetype to set
370 public void setMimetype(String mimetype
) {
371 mMimeType
= mimetype
;
375 * Sets the ID of the parent folder
377 * @param parent_id to set
379 public void setParentId(long parent_id
) {
380 mParentId
= parent_id
;
384 * Sets the file size in bytes
386 * @param file_len to set
388 public void setFileLength(long file_len
) {
393 * Returns the size of the file in bytes
395 * @return The filesize in bytes
397 public long getFileLength() {
402 * Returns the ID of the parent Folder
406 public long getParentId() {
411 * Check, if this file needs updating
415 public boolean needsUpdatingWhileSaving() {
416 return mNeedsUpdating
;
419 public boolean needsUpdateThumbnail() {
420 return mNeedsUpdateThumbnail
;
423 public void setNeedsUpdateThumbnail(boolean needsUpdateThumbnail
) {
424 this.mNeedsUpdateThumbnail
= needsUpdateThumbnail
;
427 public long getLastSyncDateForProperties() {
428 return mLastSyncDateForProperties
;
431 public void setLastSyncDateForProperties(long lastSyncDate
) {
432 mLastSyncDateForProperties
= lastSyncDate
;
435 public long getLastSyncDateForData() {
436 return mLastSyncDateForData
;
439 public void setLastSyncDateForData(long lastSyncDate
) {
440 mLastSyncDateForData
= lastSyncDate
;
443 public void setFavorite(boolean favorite
) {
444 mFavorite
= favorite
;
447 public boolean isFavorite() {
452 public int describeContents() {
453 return super.hashCode();
457 public int compareTo(OCFile another
) {
458 if (isFolder() && another
.isFolder()) {
459 return getRemotePath().toLowerCase().compareTo(another
.getRemotePath().toLowerCase());
460 } else if (isFolder()) {
462 } else if (another
.isFolder()) {
465 return new AlphanumComparator().compare(this, another
);
469 public boolean equals(Object o
) {
470 if (o
instanceof OCFile
) {
471 OCFile that
= (OCFile
) o
;
473 return this.mId
== that
.mId
;
481 public String
toString() {
482 String asString
= "[id=%s, name=%s, mime=%s, downloaded=%s, local=%s, remote=%s, " +
483 "parentId=%s, favorite=%s etag=%s]";
484 asString
= String
.format(asString
, Long
.valueOf(mId
), getFileName(), mMimeType
, isDown(),
485 mLocalPath
, mRemotePath
, Long
.valueOf(mParentId
), Boolean
.valueOf(mFavorite
),
490 public String
getEtag() {
494 public void setEtag(String etag
) {
495 this.mEtag
= (etag
!= null ? etag
: "");
499 public boolean isSharedViaLink() {
503 public void setShareViaLink(boolean shareByLink
) {
504 this.mShareByLink
= shareByLink
;
507 public String
getPublicLink() {
511 public void setPublicLink(String publicLink
) {
512 this.mPublicLink
= publicLink
;
515 public long getLocalModificationTimestamp() {
516 if (mLocalPath
!= null
&& mLocalPath
.length() > 0) {
517 File f
= new File(mLocalPath
);
518 return f
.lastModified();
524 * @return 'True' if the file contains audio
526 public boolean isAudio() {
527 return (mMimeType
!= null
&& mMimeType
.startsWith("audio/"));
531 * @return 'True' if the file contains video
533 public boolean isVideo() {
534 return (mMimeType
!= null
&& mMimeType
.startsWith("video/"));
538 * @return 'True' if the file contains an image
540 public boolean isImage() {
541 return ((mMimeType
!= null
&& mMimeType
.startsWith("image/")) ||
542 getMimeTypeFromName().startsWith("image/"));
546 * @return 'True' if the file is simple text (e.g. not application-dependent, like .doc or .docx)
548 public boolean isText() {
549 return ((mMimeType
!= null
&& mMimeType
.startsWith("text/")) ||
550 getMimeTypeFromName().startsWith("text/"));
553 public String
getMimeTypeFromName() {
554 String extension
= "";
555 int pos
= mRemotePath
.lastIndexOf('.');
557 extension
= mRemotePath
.substring(pos
+ 1);
559 String result
= MimeTypeMap
.getSingleton().
560 getMimeTypeFromExtension(extension
.toLowerCase());
561 return (result
!= null
) ? result
: "";
565 * @return 'True' if the file is hidden
567 public boolean isHidden() {
568 return getFileName().startsWith(".");
571 public String
getPermissions() {
575 public void setPermissions(String permissions
) {
576 this.mPermissions
= permissions
;
579 public String
getRemoteId() {
583 public void setRemoteId(String remoteId
) {
584 this.mRemoteId
= remoteId
;
587 public boolean isDownloading() {
588 return mIsDownloading
;
591 public void setDownloading(boolean isDownloading
) {
592 this.mIsDownloading
= isDownloading
;
595 public String
getEtagInConflict() {
596 return mEtagInConflict
;
599 public void setEtagInConflict(String etagInConflict
) {
600 mEtagInConflict
= etagInConflict
;
603 public boolean isSharedViaUsers() {
604 return mShareWithUser
;
607 public void setShareViaUsers(boolean shareWithUser
) {
608 this.mShareWithUser
= shareWithUser
;
611 public boolean isSharedWithMe() {
612 String permissions
= getPermissions();
613 return (permissions
!= null
&& permissions
.contains(PERMISSION_SHARED_WITH_ME
));