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