OC-1250: Fix bug - App crashes when you enter in an account with a lot of files
[pub/Android/ownCloud.git] / src / com / owncloud / android / datamodel / FileDataStorageManager.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 import java.util.ArrayList;
23 import java.util.Collections;
24 import java.util.Iterator;
25 import java.util.List;
26 import java.util.Vector;
27
28 import com.owncloud.android.DisplayUtils;
29 import com.owncloud.android.Log_OC;
30 import com.owncloud.android.db.ProviderMeta;
31 import com.owncloud.android.db.ProviderMeta.ProviderTableMeta;
32 import com.owncloud.android.utils.FileStorageUtils;
33
34 import android.accounts.Account;
35 import android.content.ContentProviderClient;
36 import android.content.ContentProviderOperation;
37 import android.content.ContentProviderResult;
38 import android.content.ContentResolver;
39 import android.content.ContentValues;
40 import android.content.OperationApplicationException;
41 import android.database.Cursor;
42 import android.net.Uri;
43 import android.os.RemoteException;
44
45 public class FileDataStorageManager implements DataStorageManager {
46
47 private ContentResolver mContentResolver;
48 private ContentProviderClient mContentProvider;
49 private Account mAccount;
50
51 private static String TAG = "FileDataStorageManager";
52
53 public FileDataStorageManager(Account account, ContentResolver cr) {
54 mContentProvider = null;
55 mContentResolver = cr;
56 mAccount = account;
57 }
58
59 public FileDataStorageManager(Account account, ContentProviderClient cp) {
60 mContentProvider = cp;
61 mContentResolver = null;
62 mAccount = account;
63 }
64
65 @Override
66 public OCFile getFileByPath(String path) {
67 Cursor c = getCursorForValue(ProviderTableMeta.FILE_PATH, path);
68 OCFile file = null;
69 if (c.moveToFirst()) {
70 file = createFileInstance(c);
71 }
72 c.close();
73 if (file == null && OCFile.PATH_SEPARATOR.equals(path)) {
74 return createRootDir(); // root should always exist
75 }
76 return file;
77 }
78
79
80 private OCFile createRootDir() {
81 OCFile file = new OCFile(OCFile.PATH_SEPARATOR);
82 file.setMimetype("DIR");
83 file.setParentId(DataStorageManager.ROOT_PARENT_ID);
84 saveFile(file);
85 return file;
86 }
87
88 @Override
89 public OCFile getFileById(long id) {
90 Cursor c = getCursorForValue(ProviderTableMeta._ID, String.valueOf(id));
91 OCFile file = null;
92 if (c.moveToFirst()) {
93 file = createFileInstance(c);
94 }
95 c.close();
96 return file;
97 }
98
99 public OCFile getFileByLocalPath(String path) {
100 Cursor c = getCursorForValue(ProviderTableMeta.FILE_STORAGE_PATH, path);
101 OCFile file = null;
102 if (c.moveToFirst()) {
103 file = createFileInstance(c);
104 }
105 c.close();
106 return file;
107 }
108
109 @Override
110 public boolean fileExists(long id) {
111 return fileExists(ProviderTableMeta._ID, String.valueOf(id));
112 }
113
114 @Override
115 public boolean fileExists(String path) {
116 return fileExists(ProviderTableMeta.FILE_PATH, path);
117 }
118
119 @Override
120 public boolean saveFile(OCFile file) {
121 boolean overriden = false;
122 ContentValues cv = new ContentValues();
123 cv.put(ProviderTableMeta.FILE_MODIFIED, file.getModificationTimestamp());
124 cv.put(ProviderTableMeta.FILE_MODIFIED_AT_LAST_SYNC_FOR_DATA, file.getModificationTimestampAtLastSyncForData());
125 cv.put(ProviderTableMeta.FILE_CREATION, file.getCreationTimestamp());
126 cv.put(ProviderTableMeta.FILE_CONTENT_LENGTH, file.getFileLength());
127 cv.put(ProviderTableMeta.FILE_CONTENT_TYPE, file.getMimetype());
128 cv.put(ProviderTableMeta.FILE_NAME, file.getFileName());
129 if (file.getParentId() != 0)
130 cv.put(ProviderTableMeta.FILE_PARENT, file.getParentId());
131 cv.put(ProviderTableMeta.FILE_PATH, file.getRemotePath());
132 if (!file.isDirectory())
133 cv.put(ProviderTableMeta.FILE_STORAGE_PATH, file.getStoragePath());
134 cv.put(ProviderTableMeta.FILE_ACCOUNT_OWNER, mAccount.name);
135 cv.put(ProviderTableMeta.FILE_LAST_SYNC_DATE, file.getLastSyncDateForProperties());
136 cv.put(ProviderTableMeta.FILE_LAST_SYNC_DATE_FOR_DATA, file.getLastSyncDateForData());
137 cv.put(ProviderTableMeta.FILE_KEEP_IN_SYNC, file.keepInSync() ? 1 : 0);
138 cv.put(ProviderTableMeta.FILE_ETAG, file.getEtag());
139
140 boolean sameRemotePath = fileExists(file.getRemotePath());
141 boolean changesSizeOfAncestors = false;
142 if (sameRemotePath ||
143 fileExists(file.getFileId()) ) { // for renamed files; no more delete and create
144
145 OCFile oldFile = null;
146 if (sameRemotePath) {
147 oldFile = getFileByPath(file.getRemotePath());
148 file.setFileId(oldFile.getFileId());
149 } else {
150 oldFile = getFileById(file.getFileId());
151 }
152 changesSizeOfAncestors = (oldFile.getFileLength() != file.getFileLength());
153
154 overriden = true;
155 if (getContentResolver() != null) {
156 getContentResolver().update(ProviderTableMeta.CONTENT_URI, cv,
157 ProviderTableMeta._ID + "=?",
158 new String[] { String.valueOf(file.getFileId()) });
159 } else {
160 try {
161 getContentProvider().update(ProviderTableMeta.CONTENT_URI,
162 cv, ProviderTableMeta._ID + "=?",
163 new String[] { String.valueOf(file.getFileId()) });
164 } catch (RemoteException e) {
165 Log_OC.e(TAG,
166 "Fail to insert insert file to database "
167 + e.getMessage());
168 }
169 }
170 } else {
171 changesSizeOfAncestors = true;
172 Uri result_uri = null;
173 if (getContentResolver() != null) {
174 result_uri = getContentResolver().insert(
175 ProviderTableMeta.CONTENT_URI_FILE, cv);
176 } else {
177 try {
178 result_uri = getContentProvider().insert(
179 ProviderTableMeta.CONTENT_URI_FILE, cv);
180 } catch (RemoteException e) {
181 Log_OC.e(TAG,
182 "Fail to insert insert file to database "
183 + e.getMessage());
184 }
185 }
186 if (result_uri != null) {
187 long new_id = Long.parseLong(result_uri.getPathSegments()
188 .get(1));
189 file.setFileId(new_id);
190 }
191 }
192
193 if (file.isDirectory()) {
194 calculateFolderSize(file.getFileId());
195 if (file.needsUpdatingWhileSaving()) {
196 for (OCFile f : getDirectoryContent(file))
197 saveFile(f);
198 }
199 }
200
201 if (changesSizeOfAncestors || file.isDirectory()) {
202 updateSizesToTheRoot(file.getParentId());
203 }
204
205 return overriden;
206 }
207
208
209 @Override
210 public void saveFiles(List<OCFile> files) {
211
212 Iterator<OCFile> filesIt = files.iterator();
213 ArrayList<ContentProviderOperation> operations = new ArrayList<ContentProviderOperation>(files.size());
214 OCFile file = null;
215
216 // prepare operations to perform
217 while (filesIt.hasNext()) {
218 file = filesIt.next();
219 ContentValues cv = new ContentValues();
220 cv.put(ProviderTableMeta.FILE_MODIFIED, file.getModificationTimestamp());
221 cv.put(ProviderTableMeta.FILE_MODIFIED_AT_LAST_SYNC_FOR_DATA, file.getModificationTimestampAtLastSyncForData());
222 cv.put(ProviderTableMeta.FILE_CREATION, file.getCreationTimestamp());
223 cv.put(ProviderTableMeta.FILE_CONTENT_LENGTH, file.getFileLength());
224 cv.put(ProviderTableMeta.FILE_CONTENT_TYPE, file.getMimetype());
225 cv.put(ProviderTableMeta.FILE_NAME, file.getFileName());
226 if (file.getParentId() != 0)
227 cv.put(ProviderTableMeta.FILE_PARENT, file.getParentId());
228 cv.put(ProviderTableMeta.FILE_PATH, file.getRemotePath());
229 if (!file.isDirectory())
230 cv.put(ProviderTableMeta.FILE_STORAGE_PATH, file.getStoragePath());
231 cv.put(ProviderTableMeta.FILE_ACCOUNT_OWNER, mAccount.name);
232 cv.put(ProviderTableMeta.FILE_LAST_SYNC_DATE, file.getLastSyncDateForProperties());
233 cv.put(ProviderTableMeta.FILE_LAST_SYNC_DATE_FOR_DATA, file.getLastSyncDateForData());
234 cv.put(ProviderTableMeta.FILE_KEEP_IN_SYNC, file.keepInSync() ? 1 : 0);
235 cv.put(ProviderTableMeta.FILE_ETAG, file.getEtag());
236
237 if (fileExists(file.getRemotePath())) {
238 OCFile oldFile = getFileByPath(file.getRemotePath());
239 file.setFileId(oldFile.getFileId());
240
241 if (file.isDirectory()) {
242 cv.put(ProviderTableMeta.FILE_CONTENT_LENGTH, oldFile.getFileLength());
243 file.setFileLength(oldFile.getFileLength());
244 }
245
246 operations.add(ContentProviderOperation.newUpdate(ProviderTableMeta.CONTENT_URI).
247 withValues(cv).
248 withSelection( ProviderTableMeta._ID + "=?",
249 new String[] { String.valueOf(file.getFileId()) })
250 .build());
251
252 } else if (fileExists(file.getFileId())) {
253 OCFile oldFile = getFileById(file.getFileId());
254 if (file.getStoragePath() == null && oldFile.getStoragePath() != null)
255 file.setStoragePath(oldFile.getStoragePath());
256
257 if (!file.isDirectory())
258 cv.put(ProviderTableMeta.FILE_STORAGE_PATH, file.getStoragePath());
259 else {
260 cv.put(ProviderTableMeta.FILE_CONTENT_LENGTH, oldFile.getFileLength());
261 file.setFileLength(oldFile.getFileLength());
262 }
263
264 operations.add(ContentProviderOperation.newUpdate(ProviderTableMeta.CONTENT_URI).
265 withValues(cv).
266 withSelection( ProviderTableMeta._ID + "=?",
267 new String[] { String.valueOf(file.getFileId()) })
268 .build());
269
270 } else {
271 operations.add(ContentProviderOperation.newInsert(ProviderTableMeta.CONTENT_URI).withValues(cv).build());
272 }
273 }
274
275 // apply operations in batch
276 ContentProviderResult[] results = null;
277 try {
278 if (getContentResolver() != null) {
279 results = getContentResolver().applyBatch(ProviderMeta.AUTHORITY_FILES, operations);
280
281 } else {
282 results = getContentProvider().applyBatch(operations);
283 }
284
285 } catch (OperationApplicationException e) {
286 Log_OC.e(TAG, "Fail to update/insert list of files to database " + e.getMessage());
287
288 } catch (RemoteException e) {
289 Log_OC.e(TAG, "Fail to update/insert list of files to database " + e.getMessage());
290 }
291
292 // update new id in file objects for insertions
293 if (results != null) {
294 long newId;
295 for (int i=0; i<results.length; i++) {
296 if (results[i].uri != null) {
297 newId = Long.parseLong(results[i].uri.getPathSegments().get(1));
298 files.get(i).setFileId(newId);
299 //Log_OC.v(TAG, "Found and added id in insertion for " + files.get(i).getRemotePath());
300 }
301 }
302 }
303
304 for (OCFile aFile : files) {
305 if (aFile.isDirectory() && aFile.needsUpdatingWhileSaving())
306 saveFiles(getDirectoryContent(aFile));
307 }
308
309 }
310
311 public void setAccount(Account account) {
312 mAccount = account;
313 }
314
315 public Account getAccount() {
316 return mAccount;
317 }
318
319 public void setContentResolver(ContentResolver cr) {
320 mContentResolver = cr;
321 }
322
323 public ContentResolver getContentResolver() {
324 return mContentResolver;
325 }
326
327 public void setContentProvider(ContentProviderClient cp) {
328 mContentProvider = cp;
329 }
330
331 public ContentProviderClient getContentProvider() {
332 return mContentProvider;
333 }
334
335 @Override
336 public Vector<OCFile> getDirectoryContent(OCFile f) {
337 if (f != null && f.isDirectory() && f.getFileId() != -1) {
338 return getDirectoryContent(f.getFileId());
339
340 } else {
341 return new Vector<OCFile>();
342 }
343 }
344
345 private Vector<OCFile> getDirectoryContent(long parentId) {
346
347 Vector<OCFile> ret = new Vector<OCFile>();
348
349 Uri req_uri = Uri.withAppendedPath(
350 ProviderTableMeta.CONTENT_URI_DIR,
351 String.valueOf(parentId));
352 Cursor c = null;
353
354 if (getContentProvider() != null) {
355 try {
356 c = getContentProvider().query(req_uri, null,
357 ProviderTableMeta.FILE_PARENT + "=?" ,
358 new String[] { String.valueOf(parentId)}, null);
359 } catch (RemoteException e) {
360 Log_OC.e(TAG, e.getMessage());
361 return ret;
362 }
363 } else {
364 c = getContentResolver().query(req_uri, null,
365 ProviderTableMeta.FILE_PARENT + "=?" ,
366 new String[] { String.valueOf(parentId)}, null);
367 }
368
369 if (c.moveToFirst()) {
370 do {
371 OCFile child = createFileInstance(c);
372 ret.add(child);
373 } while (c.moveToNext());
374 }
375
376 c.close();
377
378 Collections.sort(ret);
379
380 return ret;
381 }
382
383
384
385 private boolean fileExists(String cmp_key, String value) {
386 Cursor c;
387 if (getContentResolver() != null) {
388 c = getContentResolver()
389 .query(ProviderTableMeta.CONTENT_URI,
390 null,
391 cmp_key + "=? AND "
392 + ProviderTableMeta.FILE_ACCOUNT_OWNER
393 + "=?",
394 new String[] { value, mAccount.name }, null);
395 } else {
396 try {
397 c = getContentProvider().query(
398 ProviderTableMeta.CONTENT_URI,
399 null,
400 cmp_key + "=? AND "
401 + ProviderTableMeta.FILE_ACCOUNT_OWNER + "=?",
402 new String[] { value, mAccount.name }, null);
403 } catch (RemoteException e) {
404 Log_OC.e(TAG,
405 "Couldn't determine file existance, assuming non existance: "
406 + e.getMessage());
407 return false;
408 }
409 }
410 boolean retval = c.moveToFirst();
411 c.close();
412 return retval;
413 }
414
415 private Cursor getCursorForValue(String key, String value) {
416 Cursor c = null;
417 if (getContentResolver() != null) {
418 c = getContentResolver()
419 .query(ProviderTableMeta.CONTENT_URI,
420 null,
421 key + "=? AND "
422 + ProviderTableMeta.FILE_ACCOUNT_OWNER
423 + "=?",
424 new String[] { value, mAccount.name }, null);
425 } else {
426 try {
427 c = getContentProvider().query(
428 ProviderTableMeta.CONTENT_URI,
429 null,
430 key + "=? AND " + ProviderTableMeta.FILE_ACCOUNT_OWNER
431 + "=?", new String[] { value, mAccount.name },
432 null);
433 } catch (RemoteException e) {
434 Log_OC.e(TAG, "Could not get file details: " + e.getMessage());
435 c = null;
436 }
437 }
438 return c;
439 }
440
441 private OCFile createFileInstance(Cursor c) {
442 OCFile file = null;
443 if (c != null) {
444 file = new OCFile(c.getString(c
445 .getColumnIndex(ProviderTableMeta.FILE_PATH)));
446 file.setFileId(c.getLong(c.getColumnIndex(ProviderTableMeta._ID)));
447 file.setParentId(c.getLong(c
448 .getColumnIndex(ProviderTableMeta.FILE_PARENT)));
449 file.setMimetype(c.getString(c
450 .getColumnIndex(ProviderTableMeta.FILE_CONTENT_TYPE)));
451 if (!file.isDirectory()) {
452 file.setStoragePath(c.getString(c
453 .getColumnIndex(ProviderTableMeta.FILE_STORAGE_PATH)));
454 if (file.getStoragePath() == null) {
455 // try to find existing file and bind it with current account; - with the current update of SynchronizeFolderOperation, this won't be necessary anymore after a full synchronization of the account
456 File f = new File(FileStorageUtils.getDefaultSavePathFor(mAccount.name, file));
457 if (f.exists()) {
458 file.setStoragePath(f.getAbsolutePath());
459 file.setLastSyncDateForData(f.lastModified());
460 }
461 }
462 }
463 file.setFileLength(c.getLong(c
464 .getColumnIndex(ProviderTableMeta.FILE_CONTENT_LENGTH)));
465 file.setCreationTimestamp(c.getLong(c
466 .getColumnIndex(ProviderTableMeta.FILE_CREATION)));
467 file.setModificationTimestamp(c.getLong(c
468 .getColumnIndex(ProviderTableMeta.FILE_MODIFIED)));
469 file.setModificationTimestampAtLastSyncForData(c.getLong(c
470 .getColumnIndex(ProviderTableMeta.FILE_MODIFIED_AT_LAST_SYNC_FOR_DATA)));
471 file.setLastSyncDateForProperties(c.getLong(c
472 .getColumnIndex(ProviderTableMeta.FILE_LAST_SYNC_DATE)));
473 file.setLastSyncDateForData(c.getLong(c.
474 getColumnIndex(ProviderTableMeta.FILE_LAST_SYNC_DATE_FOR_DATA)));
475 file.setKeepInSync(c.getInt(
476 c.getColumnIndex(ProviderTableMeta.FILE_KEEP_IN_SYNC)) == 1 ? true : false);
477 file.setEtag(c.getString(c.getColumnIndex(ProviderTableMeta.FILE_ETAG)));
478
479 }
480 return file;
481 }
482
483 @Override
484 public void removeFile(OCFile file, boolean removeLocalCopy) {
485 Uri file_uri = Uri.withAppendedPath(ProviderTableMeta.CONTENT_URI_FILE, ""+file.getFileId());
486 if (getContentProvider() != null) {
487 try {
488 getContentProvider().delete(file_uri,
489 ProviderTableMeta.FILE_ACCOUNT_OWNER+"=?",
490 new String[]{mAccount.name});
491 } catch (RemoteException e) {
492 e.printStackTrace();
493 }
494 } else {
495 getContentResolver().delete(file_uri,
496 ProviderTableMeta.FILE_ACCOUNT_OWNER+"=?",
497 new String[]{mAccount.name});
498 }
499 if (file.isDown() && removeLocalCopy) {
500 new File(file.getStoragePath()).delete();
501 }
502 if (file.isDirectory() && removeLocalCopy) {
503 File f = new File(FileStorageUtils.getDefaultSavePathFor(mAccount.name, file));
504 if (f.exists() && f.isDirectory() && (f.list() == null || f.list().length == 0)) {
505 f.delete();
506 }
507 }
508
509 if (file.getFileLength() > 0) {
510 updateSizesToTheRoot(file.getParentId());
511 }
512 }
513
514 @Override
515 public void removeDirectory(OCFile dir, boolean removeDBData, boolean removeLocalContent) {
516 // TODO consider possible failures
517 if (dir != null && dir.isDirectory() && dir.getFileId() != -1) {
518 Vector<OCFile> children = getDirectoryContent(dir);
519 if (children.size() > 0) {
520 OCFile child = null;
521 for (int i=0; i<children.size(); i++) {
522 child = children.get(i);
523 if (child.isDirectory()) {
524 removeDirectory(child, removeDBData, removeLocalContent);
525 } else {
526 if (removeDBData) {
527 removeFile(child, removeLocalContent);
528 } else if (removeLocalContent) {
529 if (child.isDown()) {
530 new File(child.getStoragePath()).delete();
531 }
532 }
533 }
534 }
535 }
536 if (removeDBData) {
537 removeFile(dir, true);
538 }
539
540 if (dir.getFileLength() > 0) {
541 updateSizesToTheRoot(dir.getParentId());
542 }
543 }
544 }
545
546
547 /**
548 * Updates database for a folder that was moved to a different location.
549 *
550 * TODO explore better (faster) implementations
551 * TODO throw exceptions up !
552 */
553 @Override
554 public void moveDirectory(OCFile dir, String newPath) {
555 // TODO check newPath
556
557 if (dir != null && dir.isDirectory() && dir.fileExists() && !dir.getFileName().equals(OCFile.PATH_SEPARATOR)) {
558 /// 1. get all the descendants of 'dir' in a single QUERY (including 'dir')
559 Cursor c = null;
560 if (getContentProvider() != null) {
561 try {
562 c = getContentProvider().query(ProviderTableMeta.CONTENT_URI,
563 null,
564 ProviderTableMeta.FILE_ACCOUNT_OWNER + "=? AND " + ProviderTableMeta.FILE_PATH + " LIKE ?",
565 new String[] { mAccount.name, dir.getRemotePath() + "%" }, null);
566 } catch (RemoteException e) {
567 Log_OC.e(TAG, e.getMessage());
568 }
569 } else {
570 c = getContentResolver().query(ProviderTableMeta.CONTENT_URI,
571 null,
572 ProviderTableMeta.FILE_ACCOUNT_OWNER + "=? AND " + ProviderTableMeta.FILE_PATH + " LIKE ?",
573 new String[] { mAccount.name, dir.getRemotePath() + "%" }, null);
574 }
575
576 /// 2. prepare a batch of update operations to change all the descendants
577 ArrayList<ContentProviderOperation> operations = new ArrayList<ContentProviderOperation>(c.getCount());
578 int lengthOfOldPath = dir.getRemotePath().length();
579 String defaultSavePath = FileStorageUtils.getSavePath(mAccount.name);
580 int lengthOfOldStoragePath = defaultSavePath.length() + lengthOfOldPath;
581 if (c.moveToFirst()) {
582 do {
583 ContentValues cv = new ContentValues(); // don't take the constructor out of the loop and clear the object
584 OCFile child = createFileInstance(c);
585 cv.put(ProviderTableMeta.FILE_PATH, newPath + child.getRemotePath().substring(lengthOfOldPath));
586 if (child.getStoragePath() != null && child.getStoragePath().startsWith(defaultSavePath)) {
587 cv.put(ProviderTableMeta.FILE_STORAGE_PATH, defaultSavePath + newPath + child.getStoragePath().substring(lengthOfOldStoragePath));
588 }
589 operations.add(ContentProviderOperation.newUpdate(ProviderTableMeta.CONTENT_URI).
590 withValues(cv).
591 withSelection( ProviderTableMeta._ID + "=?",
592 new String[] { String.valueOf(child.getFileId()) })
593 .build());
594 } while (c.moveToNext());
595 }
596 c.close();
597
598 /// 3. apply updates in batch
599 try {
600 if (getContentResolver() != null) {
601 getContentResolver().applyBatch(ProviderMeta.AUTHORITY_FILES, operations);
602
603 } else {
604 getContentProvider().applyBatch(operations);
605 }
606
607 } catch (OperationApplicationException e) {
608 Log_OC.e(TAG, "Fail to update descendants of " + dir.getFileId() + " in database", e);
609
610 } catch (RemoteException e) {
611 Log_OC.e(TAG, "Fail to update desendants of " + dir.getFileId() + " in database", e);
612 }
613
614 }
615 }
616
617 @Override
618 public Vector<OCFile> getDirectoryImages(OCFile directory) {
619 Vector<OCFile> ret = new Vector<OCFile>();
620 if (directory != null) {
621 // TODO better implementation, filtering in the access to database (if possible) instead of here
622 Vector<OCFile> tmp = getDirectoryContent(directory);
623 OCFile current = null;
624 for (int i=0; i<tmp.size(); i++) {
625 current = tmp.get(i);
626 if (current.isImage()) {
627 ret.add(current);
628 }
629 }
630 }
631 return ret;
632 }
633
634 /**
635 * Calculate and save the folderSize on DB
636 * @param id
637 */
638 @Override
639 public void calculateFolderSize(long id) {
640 long folderSize = 0;
641
642 Vector<OCFile> files = getDirectoryContent(id);
643
644 for (OCFile f: files)
645 {
646 folderSize = folderSize + f.getFileLength();
647 }
648
649 updateSize(id, folderSize);
650 }
651
652 /**
653 * Update the size value of an OCFile in DB
654 */
655 private int updateSize(long id, long size) {
656 ContentValues cv = new ContentValues();
657 cv.put(ProviderTableMeta.FILE_CONTENT_LENGTH, size);
658 int result = -1;
659 if (getContentResolver() != null) {
660 result = getContentResolver().update(ProviderTableMeta.CONTENT_URI, cv, ProviderTableMeta._ID + "=?",
661 new String[] { String.valueOf(id) });
662 } else {
663 try {
664 result = getContentProvider().update(ProviderTableMeta.CONTENT_URI, cv, ProviderTableMeta._ID + "=?",
665 new String[] { String.valueOf(id) });
666 } catch (RemoteException e) {
667 Log_OC.e(TAG,"Fail to update size column into database " + e.getMessage());
668 }
669 }
670 return result;
671 }
672
673 /**
674 * Update the size of a subtree of folder from a file to the root
675 * @param parentId: parent of the file
676 */
677 private void updateSizesToTheRoot(long parentId) {
678
679 OCFile file;
680
681 while (parentId != 0) {
682
683 Log_OC.d(TAG, "parent = " + parentId);
684 // Update the size of the parent
685 calculateFolderSize(parentId);
686
687 // search the next parent
688 file = getFileById(parentId);
689 parentId = file.getParentId();
690
691 }
692
693 }
694
695 }